diff --git a/.gitignore b/.gitignore index 2480b83823..1fc3016d3f 100644 --- a/.gitignore +++ b/.gitignore @@ -11,10 +11,6 @@ .deps .\#* \#* -/Debug/ -/Release/ -/All/ -/bin/ *.user *.suo *.ncb @@ -39,105 +35,115 @@ *.xz *.bz2 *.tbz2 +aclocal.m4 +autom4te.cache +config.cache +configure.lineno +config.log +config.status core.* -/Path + /w32/Library/lastversion /w32/Library/tmpVersion.Bat !/w32/Console/FreeSwitchConsole.vcproj.user !/w32/Setup/inno_setup/vcredist_x64.exe !/w32/Setup/inno_setup/vcredist_x86.exe -.version -AUTHORS -COPYING -ChangeLog -Makefile -Makefile.in -NEWS -README -TAGS -aclocal.m4 -autom4te.cache -build/Makefile -build/Makefile.in -build/config/compile -build/config/config.guess -build/config/depcomp -build/config/install-sh -build/config/ltmain.sh -build/config/missing -build/freeswitch.pc -build/getlib.sh -build/getsounds.sh -build/modmake.rules -build/getg729.sh -config.cache -config.log -config.status -configure -configure.lineno -freeswitch -fs_cli -fs_encode -fs_ivrd -libtool -noreg -modules.conf -quiet_libtool -tone2wav -scripts/fsxs -scripts/gentls_cert -a.out.dSYM -src/mod/applications/mod_easyroute/Makefile -src/mod/applications/mod_lcr/Makefile -src/mod/applications/mod_nibblebill/Makefile -src/mod/applications/mod_rss/Makefile -src/mod/applications/mod_snipe_hunt/Makefile -src/mod/codecs/mod_dahdi_codec/Makefile -src/mod/dialplans/mod_dialplan_directory/Makefile -src/mod/formats/mod_shell_stream/Makefile -src/mod/say/mod_say_de/Makefile -src/mod/say/mod_say_es/Makefile -src/mod/say/mod_say_fr/Makefile -src/mod/say/mod_say_it/Makefile -src/mod/say/mod_say_nl/Makefile -src/mod/say/mod_say_th/Makefile -src/mod/say/mod_say_zh/Makefile -libs/curl/lib/ca-bundle.h -libs/g729/ -libs/fsg729-*-installer -src/mod/codecs/mod_com_g729/ -src/mod/languages/mod_lua/mod_lua_wrap.cpp.orig -src/mod/languages/mod_perl/mod_perl_wrap.cpp.orig -src/mod/languages/mod_python/mod_python_wrap.cpp.orig -libs/freetdm/detect_dtmf -libs/freetdm/detect_tones -libs/freetdm/testanalog -libs/freetdm/testapp -libs/freetdm/testcid -libs/freetdm/testpri -libs/freetdm/testr2 -libs/freetdm/testsangomaboost -libs/freetdm/testtones -libs/esl/fs_cli -libs/esl/ivrd -libs/esl/testserver -libs/esl/testclient -libs/libcodec2/Makefile -libs/libcodec2/Makefile.in -libs/libcodec2/config.guess -libs/libcodec2/config.sub -libs/libcodec2/configure -libs/libcodec2/depcomp -libs/libcodec2/install-sh -libs/libcodec2/libtool -libs/libcodec2/ltmain.sh -libs/libcodec2/missing -libs/libcodec2/src/Makefile -libs/libcodec2/src/Makefile.in -libs/libcodec2/unittest/Makefile -libs/libcodec2/unittest/Makefile.in -src/mod/applications/mod_osp/Makefile -src/mod/applications/mod_osp/Makefile.in -src/mod/applications/mod_hash/Makefile -src/mod/applications/mod_hash/Makefile.in -src/mod/applications/mod_hash/mod_hash.log + +/.version +/a.out.dSYM +/AUTHORS +/ChangeLog +/configure +/COPYING +/freeswitch +/fs_cli +/fs_encode +/fs_ivrd +/libtool +/Makefile +/Makefile.in +/modules.conf +/NEWS +/Path +/quiet_libtool +/README +/TAGS +/tone2wav + +/All/ +/Debug/ +/bin/ +/Release/ + +/build/config/compile +/build/config/config.guess +/build/config/depcomp +/build/config/install-sh +/build/config/ltmain.sh +/build/config/missing +/build/freeswitch.pc +/build/getlib.sh +/build/getsounds.sh +/build/Makefile +/build/Makefile.in +/build/modmake.rules + +/libs/curl/lib/ca-bundle.h +/libs/esl/fs_cli +/libs/esl/ivrd +/libs/esl/testclient +/libs/esl/testserver +/libs/freetdm/detect_dtmf +/libs/freetdm/detect_tones +/libs/freetdm/testanalog +/libs/freetdm/testapp +/libs/freetdm/testcid +/libs/freetdm/testpri +/libs/freetdm/testr2 +/libs/freetdm/testsangomaboost +/libs/freetdm/testtones +/libs/fsg729-*-installer +/libs/g729/ +/libs/libcodec2/config.guess +/libs/libcodec2/config.sub +/libs/libcodec2/configure +/libs/libcodec2/depcomp +/libs/libcodec2/install-sh +/libs/libcodec2/libtool +/libs/libcodec2/ltmain.sh +/libs/libcodec2/Makefile +/libs/libcodec2/Makefile.in +/libs/libcodec2/missing +/libs/libcodec2/src/Makefile +/libs/libcodec2/src/Makefile.in +/libs/libcodec2/unittest/Makefile +/libs/libcodec2/unittest/Makefile.in + +/scripts/fsxs +/scripts/gentls_cert + +/src/mod/applications/mod_easyroute/Makefile +/src/mod/applications/mod_hash/Makefile +/src/mod/applications/mod_hash/Makefile.in +/src/mod/applications/mod_hash/mod_hash.log +/src/mod/applications/mod_lcr/Makefile +/src/mod/applications/mod_nibblebill/Makefile +/src/mod/applications/mod_osp/Makefile +/src/mod/applications/mod_osp/Makefile.in +/src/mod/applications/mod_rss/Makefile +/src/mod/applications/mod_snipe_hunt/Makefile +/src/mod/codecs/mod_com_g729/ +/src/mod/codecs/mod_dahdi_codec/Makefile +/src/mod/dialplans/mod_dialplan_directory/Makefile +/src/mod/formats/mod_shell_stream/Makefile +/src/mod/languages/mod_lua/mod_lua_wrap.cpp.orig +/src/mod/languages/mod_perl/mod_perl_wrap.cpp.orig +/src/mod/languages/mod_python/mod_python_wrap.cpp.orig +/src/mod/say/mod_say_de/Makefile +/src/mod/say/mod_say_es/Makefile +/src/mod/say/mod_say_fr/Makefile +/src/mod/say/mod_say_it/Makefile +/src/mod/say/mod_say_nl/Makefile +/src/mod/say/mod_say_th/Makefile +/src/mod/say/mod_say_zh/Makefile + diff --git a/Makefile.am b/Makefile.am index 37a01d27fb..5b6b9896ac 100644 --- a/Makefile.am +++ b/Makefile.am @@ -356,7 +356,7 @@ scripts/fsxs: scripts/fsxs.in ## misc ## -pkgconfigdir = $(libdir)/pkgconfig +pkgconfigdir = @pkgconfigdir@ pkgconfig_DATA = build/freeswitch.pc $(switch_builddir)/modules.conf: diff --git a/build/getlib.sh.in b/build/getlib.sh.in index ebad7b5084..f328b87d45 100755 --- a/build/getlib.sh.in +++ b/build/getlib.sh.in @@ -1,5 +1,8 @@ #!/bin/sh +bz="false" + +BUNZIP=/usr/bin/bunzip2 TAR=@TAR@ ZCAT=@ZCAT@ WGET=@WGET@ @@ -17,14 +20,26 @@ base=http://files.freeswitch.org/downloads/libs/ tarfile=$1 url=`echo $tarfile | grep "://"` +if [ `echo $tarfile | grep bz2` ] ; then + bz="true" + UNZIPPER=$BUNZIP +else + UNZIPPER=$ZCAT +fi + if [ ! -z $url ] ; then base=$tarfile/ tarfile=$2 fi if [ ! -d $tarfile ] ; then - uncompressed=`echo $tarfile | sed "s/\.tar\.gz//g"` - uncompressed=`echo $uncompressed | sed "s/\.tgz//g"` + + if [ $bz = "true" ] ; then + uncompressed=`echo $tarfile | sed "s/\.tar\.bz2//g"` + else + uncompressed=`echo $tarfile | sed "s/\.tar\.gz//g"` + uncompressed=`echo $uncompressed | sed "s/\.tgz//g"` + fi if [ ! -f $tarfile ] ; then rm -fr $uncompressed @@ -35,7 +50,7 @@ if [ ! -d $tarfile ] ; then fi fi if [ ! -d $uncompressed ] ; then - $ZCAT -c -d $tarfile | $TAR xf - + $UNZIPPER -c -d $tarfile | $TAR xf - fi fi diff --git a/conf/autoload_configs/conference.conf.xml b/conf/autoload_configs/conference.conf.xml index cab0578a57..d4e5aa60ee 100644 --- a/conf/autoload_configs/conference.conf.xml +++ b/conf/autoload_configs/conference.conf.xml @@ -52,8 +52,9 @@ - - + + + @@ -106,7 +107,7 @@ - + @@ -131,7 +132,7 @@ - + @@ -156,7 +157,7 @@ - + diff --git a/conf/autoload_configs/switch.conf.xml b/conf/autoload_configs/switch.conf.xml index 4f72c6a65d..d2500a6463 100644 --- a/conf/autoload_configs/switch.conf.xml +++ b/conf/autoload_configs/switch.conf.xml @@ -24,6 +24,11 @@ + + + + + diff --git a/conf/skinny_profiles/internal.xml b/conf/skinny_profiles/internal.xml index 52da89741d..0ca4ed0c46 100644 --- a/conf/skinny_profiles/internal.xml +++ b/conf/skinny_profiles/internal.xml @@ -16,12 +16,16 @@ - - - + + + + + + + diff --git a/conf/vars.xml b/conf/vars.xml index 0e8782cff0..94529aa9bc 100644 --- a/conf/vars.xml +++ b/conf/vars.xml @@ -207,6 +207,7 @@ + + + + diff --git a/libs/freetdm/configure.ac b/libs/freetdm/configure.ac index 38f849b9e6..55185cb10d 100644 --- a/libs/freetdm/configure.ac +++ b/libs/freetdm/configure.ac @@ -65,6 +65,18 @@ AC_ARG_WITH([modinstdir], ) AC_SUBST([modinstdir]) +# freetdm.pc pkgconfig file +AC_ARG_WITH([pkgconfigdir], + [AS_HELP_STRING([--with-pkgconfigdir=DIR], [Installation directory for pkgconfig file (default: ${libdir}/pkgconfig)])], + [case "${withval}" in + yes|no) AC_MSG_ERROR([Invalid value ${withval} for option --with-pkgconfigdir]) ;; + *) pkgconfigdir="${withval}" ;; + esac + ], + [pkgconfigdir="${libdir}/pkgconfig"] +) +AC_SUBST([pkgconfigdir]) + AC_ARG_ENABLE([enable_64], [AS_HELP_STRING([--enable-64], [Enable 64bit compilation])], [enable_64="${enableval}"], diff --git a/libs/freetdm/docs/variables.txt b/libs/freetdm/docs/variables.txt new file mode 100644 index 0000000000..0beecd016c --- /dev/null +++ b/libs/freetdm/docs/variables.txt @@ -0,0 +1,118 @@ +Using FreeTDM Variables + +1. User application sending variables or raw buffer to FreeTDM +============================================================== + +The User can include a ftdm_usrmsg_t before sending an event to freetdm. + +example #1a - Making an outbound call: +-------------------------------------- + +To make an outbound call: + ftdm_usrmsg_t usrmsg; + + /* Attach variable to usrmsg */ + ftdm_usrmsg_add_var(&usrmsg, "isdn.prog_ind.descr", "inband-info-available"); + + ftdm_channel_call_place_ex(ftdmchan, &usrmsg); + +example #1b - Adding a variable: +-------------------------------- +When using ftmod_sangoma_isdn, user want to specify progress indicator inside PROCEED message. + + + ftdm_usrmsg_t usrmsg; + + /* Attach variable to usrmsg */ + ftdm_usrmsg_add_var(&usrmsg, "isdn.prog_ind.descr", "inband-info-available"); + + /* Request FreeTDM to send a PROCEED msg */ + ftdm_channel_call_indicate_ex(ftdmchan, FTDM_CHANNEL_INDICATE_PROCEED, &usrmsg); + + +example #2 - Setting raw data: +-------------------------------------------------------- + +When using ftmod_sangoma_isdn, user wants to transmit a custom Facility IE, inside a FACILITY message. + + ftdm_usrmsg_t usrmsg; + + uint8_t *my_facility_ie = ftdm_calloc(1, 200); /*memory has to be allocated using ftdm_calloc !! */ + unsigned my_facility_ie_len = 0; + + /* Fill my_facility_ie with custom data here */ + my_facility_ie[my_facility_ie_len++] = 0x1C; /* Q.931 Facility IE ID */ + my_facility_ie[my_facility_ie_len++] = 0x03; /* Length of facility IE */ + my_facility_ie[my_facility_ie_len++] = 0x01; + my_facility_ie[my_facility_ie_len++] = 0x02; + my_facility_ie[my_facility_ie_len++] = 0x03; + + ftdm_usrmsg_set_raw_data(&usrmsg, my_facility_ie, my_facility_ie_len); + + ftdm_channel_call_indicate(ftdmchan, FTDM_CHANNEL_INDICATE_FACILITY, &usrmsg); + + /* FreeTDM will automatically free my_facility_ie */ + + +2. User application receiving variables and raw buffer from FreeTDM +================================================================== + +example #1 - print all variables received from FreeTDM +------------------------------------------------------ + + /* Inside event call-back function */ + ftdm_iterator_t *iter = NULL; + ftdm_iterator_t *curr = NULL; + const char *var_name = NULL; + const char *var_value = NULL; + + /* Read all variables attached to this event */ + iter = ftdm_sigmsg_get_var_iterator(sigmsg, iter); + for (curr = iter ; curr; curr = ftdm_iterator_next(curr)) { + ftdm_get_current_var(curr, &var_name, &var_value); + fprintf("Call Variable: %s=%s\n", var_name, var_value); + } + ftdm_iterator_free(iter); + + +example #2 - accessing a specific variable +------------------------------------------ + + /* Inside event call-back function */ + char *string = NULL; + string = ftdm_sigmsg_get_var(sigmsg, "isdn.prog_ind.descr"); + if (string && *string) { + fprintf("Progress indicator:%s\n", string); + } + + +example #3a - accessing raw data +------------------------------- + + /* Inside event call-back function */ + ftdm_size_t len; + uint8_t *mydata; + if (ftdm_sigmsg_get_raw_data(sigmsg, (void**)&mydata, &len) == FTDM_SUCCESS) { + /* raw data is available, do something with mydata here */ + } + /* Once this function returns, raw data will be free'd inside FreeTDM */ + + +example #3b - accessing raw data +------------------------------- + + /* Inside event call-back function */ + ftdm_size_t len; + uint8_t *mydata; + if (ftdm_sigmsg_get_raw_data_detached(sigmsg, (void**)&mydata, &len) == FTDM_SUCCESS) { + /* raw data is available, do something with mydata here */ + + } + + : + : + : + + /* User owns raw data and is responsible for free'ing it*/ + ftdm_safe_free(mydata); + diff --git a/libs/freetdm/freetdm.2008.sln b/libs/freetdm/freetdm.2008.sln index 0e374545eb..4bf2c795a6 100644 --- a/libs/freetdm/freetdm.2008.sln +++ b/libs/freetdm/freetdm.2008.sln @@ -43,21 +43,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_wanpipe", "src\ftmod\ {93B8812C-3EC4-4F78-8970-FFBFC99E167D} = {93B8812C-3EC4-4F78-8970-FFBFC99E167D} EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_sangoma_boost", "src\ftmod\ftmod_sangoma_boost\ftmod_sangoma_boost.2008.vcproj", "{D021EF2A-460D-4827-A0F7-41FDECF46F1B}" - ProjectSection(ProjectDependencies) = postProject - {93B8812C-3EC4-4F78-8970-FFBFC99E167D} = {93B8812C-3EC4-4F78-8970-FFBFC99E167D} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testboost", "msvc\testboost\testboost.2008.vcproj", "{2B1BAF36-0241-43E7-B865-A8338AD48E2E}" - ProjectSection(ProjectDependencies) = postProject - {93B8812C-3EC4-4F78-8970-FFBFC99E167D} = {93B8812C-3EC4-4F78-8970-FFBFC99E167D} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testsangomaboost", "msvc\testboost\testsangomaboost.2008.vcproj", "{0DA69C18-4FA1-4E8C-89CE-12498637C5BE}" - ProjectSection(ProjectDependencies) = postProject - {93B8812C-3EC4-4F78-8970-FFBFC99E167D} = {93B8812C-3EC4-4F78-8970-FFBFC99E167D} - EndProjectSection -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_sangoma_isdn", "src\ftmod\ftmod_sangoma_isdn\ftmod_sangoma_isdn.2008.vcproj", "{B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}" ProjectSection(ProjectDependencies) = postProject {93B8812C-3EC4-4F78-8970-FFBFC99E167D} = {93B8812C-3EC4-4F78-8970-FFBFC99E167D} diff --git a/libs/freetdm/freetdm.2010.sln b/libs/freetdm/freetdm.2010.sln index 44431d675a..b6259e5960 100644 --- a/libs/freetdm/freetdm.2010.sln +++ b/libs/freetdm/freetdm.2010.sln @@ -19,12 +19,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_pika", "src\ftmod\ftm EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_wanpipe", "src\ftmod\ftmod_wanpipe\ftmod_wanpipe.2010.vcxproj", "{1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_sangoma_boost", "src\ftmod\ftmod_sangoma_boost\ftmod_sangoma_boost.2010.vcxproj", "{D021EF2A-460D-4827-A0F7-41FDECF46F1B}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testboost", "msvc\testboost\testboost.2010.vcxproj", "{2B1BAF36-0241-43E7-B865-A8338AD48E2E}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testsangomaboost", "msvc\testboost\testsangomaboost.2010.vcxproj", "{0DA69C18-4FA1-4E8C-89CE-12498637C5BE}" -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_sangoma_isdn", "src\ftmod\ftmod_sangoma_isdn\ftmod_sangoma_isdn.2010.vcxproj", "{B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftmod_r2", "src\ftmod\ftmod_r2\ftmod_r2.2010.vcxproj", "{08C3EA27-A51D-47F8-B47D-B189C649CF30}" diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index 4dc6cfcfd2..0652a8e128 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -408,8 +408,6 @@ static switch_status_t channel_on_init(switch_core_session_t *session) globals.calls++; switch_mutex_unlock(globals.mutex); - ftdm_channel_init(tech_pvt->ftdmchan); - //switch_channel_set_flag(channel, CF_ACCEPT_CNG); return SWITCH_STATUS_SUCCESS; @@ -495,7 +493,6 @@ static switch_status_t channel_on_hangup(switch_core_session_t *session) switch (chantype) { case FTDM_CHAN_TYPE_FXO: case FTDM_CHAN_TYPE_EM: - case FTDM_CHAN_TYPE_CAS: { ftdm_channel_call_hangup(tech_pvt->ftdmchan); } @@ -512,6 +509,7 @@ static switch_status_t channel_on_hangup(switch_core_session_t *session) } } break; + case FTDM_CHAN_TYPE_CAS: case FTDM_CHAN_TYPE_B: { ftdm_call_cause_t hcause = switch_channel_get_cause_q850(channel); @@ -523,8 +521,7 @@ static switch_status_t channel_on_hangup(switch_core_session_t *session) break; default: { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Unhandled channel type %d for channel %s\n", chantype, - switch_channel_get_name(channel)); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Unhandled channel type %d for channel %s\n", chantype, switch_channel_get_name(channel)); } break; } @@ -874,7 +871,7 @@ static switch_status_t channel_receive_message_b(switch_core_session_t *session, default: break; } - + return SWITCH_STATUS_SUCCESS; } @@ -1153,6 +1150,9 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi const char *var; const char *dest_num = NULL, *callerid_num = NULL; ftdm_hunting_scheme_t hunting; + ftdm_usrmsg_t usrmsg; + + memset(&usrmsg, 0, sizeof(ftdm_usrmsg_t)); if (!outbound_profile) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing caller profile\n"); @@ -1343,11 +1343,6 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi if ((var = channel_get_variable(session, var_event, "freetdm_calling_party_category"))) { ftdm_set_calling_party_category(var, (uint8_t *)&caller_data.cpc); } - - if ((var = channel_get_variable(session, var_event, "freetdm_custom_call_data"))) { - ftdm_set_string(caller_data.raw_data, var); - caller_data.raw_data_len = (uint32_t)strlen(var); - } if (!zstr(dest)) { ftdm_set_string(caller_data.dnis.digits, dest); @@ -1386,7 +1381,7 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi char *v = h->name + FREETDM_VAR_PREFIX_LEN; if (!zstr(v)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Adding outbound freetdm variable %s=%s to channel %d:%d\n", v, h->value, span_id, chan_id); - ftdm_call_add_var(&caller_data, v, h->value); + ftdm_usrmsg_add_var(&usrmsg, v, h->value); } } } @@ -1414,7 +1409,7 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi hunt_data.tech_pvt = tech_pvt; caller_data.priv = &hunt_data; - if ((status = ftdm_call_place(&caller_data, &hunting)) != FTDM_SUCCESS) { + if ((status = ftdm_call_place_ex(&caller_data, &hunting, &usrmsg)) != FTDM_SUCCESS) { if (tech_pvt->read_codec.implementation) { switch_core_codec_destroy(&tech_pvt->read_codec); } @@ -1431,8 +1426,6 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi goto fail; } - ftdm_channel_init(caller_data.fchan); - return SWITCH_CAUSE_SUCCESS; } @@ -1552,8 +1545,8 @@ ftdm_status_t ftdm_channel_from_event(ftdm_sigmsg_t *sigmsg, switch_core_session switch_channel_set_variable_printf(channel, "freetdm_chan_number", "%d", chanid); switch_channel_set_variable_printf(channel, "freetdm_bearer_capability", "%d", channel_caller_data->bearer_capability); switch_channel_set_variable_printf(channel, "freetdm_bearer_layer1", "%d", channel_caller_data->bearer_layer1); - switch_channel_set_variable_printf(channel, "freetdm_screening_ind", ftdm_screening2str(channel_caller_data->screen)); - switch_channel_set_variable_printf(channel, "freetdm_presentation_ind", ftdm_presentation2str(channel_caller_data->pres)); + switch_channel_set_variable_printf(channel, "screening_ind", ftdm_screening2str(channel_caller_data->screen)); + switch_channel_set_variable_printf(channel, "presentation_ind", ftdm_presentation2str(channel_caller_data->pres)); if (globals.sip_headers) { switch_channel_set_variable(channel, "sip_h_X-FreeTDM-SpanName", ftdm_channel_get_span_name(sigmsg->channel)); @@ -1579,20 +1572,17 @@ ftdm_status_t ftdm_channel_from_event(ftdm_sigmsg_t *sigmsg, switch_core_session switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-Screen", "%d", channel_caller_data->screen); switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-Presentation", "%d", channel_caller_data->pres); } - if (channel_caller_data->raw_data_len) { - switch_channel_set_variable_printf(channel, "freetdm_custom_call_data", "%s", channel_caller_data->raw_data); - } + /* Add any call variable to the dial plan */ - iter = ftdm_call_get_var_iterator(channel_caller_data, iter); + iter = ftdm_sigmsg_get_var_iterator(sigmsg, iter); for (curr = iter ; curr; curr = ftdm_iterator_next(curr)) { - ftdm_call_get_current_var(curr, &var_name, &var_value); + ftdm_get_current_var(curr, &var_name, &var_value); snprintf(name, sizeof(name), FREETDM_VAR_PREFIX "%s", var_name); switch_channel_set_variable_printf(channel, name, "%s", var_value); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Call Variable: %s = %s\n", name, var_value); } ftdm_iterator_free(iter); - switch_channel_set_state(channel, CS_INIT); if (switch_core_session_thread_launch(session) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error spawning thread\n"); @@ -2790,6 +2780,7 @@ static switch_status_t load_config(void) const char *hangup_polarity = "false"; int polarity_delay = 600; int callwaiting = 1; + int dialtone_timeout = 5000; uint32_t span_id = 0, to = 0, max = 0; ftdm_span_t *span = NULL; @@ -2830,6 +2821,8 @@ static switch_status_t load_config(void) tonegroup = val; } else if (!strcasecmp(var, "digit_timeout") || !strcasecmp(var, "digit-timeout")) { digit_timeout = val; + } else if (!strcasecmp(var, "wait-dialtone-timeout")) { + dialtone_timeout = atoi(val); } else if (!strcasecmp(var, "context")) { context = val; } else if (!strcasecmp(var, "dialplan")) { @@ -2930,6 +2923,7 @@ static switch_status_t load_config(void) "hangup_polarity_reverse", hangup_polarity, "polarity_delay", &polarity_delay, "callwaiting", &callwaiting, + "wait_dialtone_timeout", &dialtone_timeout, FTDM_TAG_END) != FTDM_SUCCESS) { ftdm_log(FTDM_LOG_ERROR, "Error configuring FreeTDM analog span %s\n", ftdm_span_get_name(span)); continue; diff --git a/libs/freetdm/msvc/freetdm.2008.vcproj b/libs/freetdm/msvc/freetdm.2008.vcproj index 0539ff3f42..46594bf38c 100644 --- a/libs/freetdm/msvc/freetdm.2008.vcproj +++ b/libs/freetdm/msvc/freetdm.2008.vcproj @@ -46,7 +46,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="../src/include;../src/include/private;../src/isdn/include" - PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;FREETDM_EXPORTS;TELETONE_EXPORTS" + PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;FREETDM_EXPORTS;TELETONE_EXPORTS;_WIN32_WINNT=0x0501" MinimalRebuild="true" BasicRuntimeChecks="3" RuntimeLibrary="3" @@ -122,7 +122,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="../src/include;../src/include/private;../src/isdn/include" - PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;FREETDM_EXPORTS;TELETONE_EXPORTS" + PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;FREETDM_EXPORTS;TELETONE_EXPORTS;_WIN32_WINNT=0x0501" MinimalRebuild="true" BasicRuntimeChecks="3" RuntimeLibrary="3" @@ -198,7 +198,7 @@ + + diff --git a/libs/freetdm/msvc/freetdm.2010.vcxproj b/libs/freetdm/msvc/freetdm.2010.vcxproj index aecb9ef79c..bd0605060a 100644 --- a/libs/freetdm/msvc/freetdm.2010.vcxproj +++ b/libs/freetdm/msvc/freetdm.2010.vcxproj @@ -89,7 +89,7 @@ Disabled ../src/include;../src/include/private;../src/isdn/include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;FREETDM_EXPORTS;TELETONE_EXPORTS;%(PreprocessorDefinitions) + WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;FREETDM_EXPORTS;TELETONE_EXPORTS;_WIN32_WINNT=0x0502;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebugDLL @@ -112,7 +112,7 @@ ../src/include;../src/include/private;../src/isdn/include;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;FREETDM_EXPORTS;TELETONE_EXPORTS;%(PreprocessorDefinitions) + WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;FREETDM_EXPORTS;TELETONE_EXPORTS;_WIN32_WINNT=0x0502;%(PreprocessorDefinitions) MultiThreadedDLL false false @@ -134,7 +134,7 @@ Disabled ../src/include;../src/include/private;../src/isdn/include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;FREETDM_EXPORTS;TELETONE_EXPORTS;%(PreprocessorDefinitions) + WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;FREETDM_EXPORTS;TELETONE_EXPORTS;_WIN32_WINNT=0x0502;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebugDLL @@ -161,7 +161,7 @@ ../src/include;../src/include/private;../src/isdn/include;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;FREETDM_EXPORTS;TELETONE_EXPORTS;%(PreprocessorDefinitions) + WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;FREETDM_EXPORTS;TELETONE_EXPORTS;_WIN32_WINNT=0x0502;%(PreprocessorDefinitions) MultiThreadedDLL false false @@ -203,6 +203,7 @@ + @@ -222,4 +223,4 @@ - \ No newline at end of file + diff --git a/libs/freetdm/msvc/freetdm.2010.vcxproj.filters b/libs/freetdm/msvc/freetdm.2010.vcxproj.filters index e6dc40d372..9f15c9c737 100644 --- a/libs/freetdm/msvc/freetdm.2010.vcxproj.filters +++ b/libs/freetdm/msvc/freetdm.2010.vcxproj.filters @@ -85,6 +85,9 @@ Source Files + + Source Files + Source Files @@ -131,4 +134,4 @@ Source Files - \ No newline at end of file + diff --git a/libs/freetdm/msvc/testboost/testboost.2008.vcproj b/libs/freetdm/msvc/testboost/testboost.2008.vcproj index 5707033f33..c273b3c02b 100644 --- a/libs/freetdm/msvc/testboost/testboost.2008.vcproj +++ b/libs/freetdm/msvc/testboost/testboost.2008.vcproj @@ -146,8 +146,9 @@ /> @@ -146,8 +146,9 @@ /> -# -CMAKE_MINIMUM_REQUIRED(VERSION 2.6) -PROJECT(boost) - -IF(NOT DEFINED WIN32) - INCLUDE_DIRECTORIES(/usr/local/freeswitch/include) - ADD_DEFINITIONS(-Wall) - ADD_EXECUTABLE(ftdmstart ftdmstart.c) - TARGET_LINK_LIBRARIES(ftdmstart freetdm) -ENDIF(NOT DEFINED WIN32) diff --git a/libs/freetdm/sample/boost/Makefile b/libs/freetdm/sample/boost/Makefile deleted file mode 100644 index 981f6f072f..0000000000 --- a/libs/freetdm/sample/boost/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -CC=gcc -CFLAGS=-Wall -I/usr/local/freeswitch/include -LDFLAGS=-L/usr/local/freeswitch/lib -lfreetdm - -ftdmstart: ftdmstart.o - -clean: - rm -rf ftdmstart.o - - diff --git a/libs/freetdm/sample/boost/ftdmstart.c b/libs/freetdm/sample/boost/ftdmstart.c deleted file mode 100644 index bff0664bce..0000000000 --- a/libs/freetdm/sample/boost/ftdmstart.c +++ /dev/null @@ -1,469 +0,0 @@ -/* - * Copyright (c) 2010, Sangoma Technologies - * Moises Silva - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * Sample program for the boost signaling absraction. - * Usage: testboostalone ... -d [number-to-dial-if-any] - * compile this program linking to the freetdm library (ie -lfreetdm) - **/ - -#ifndef __linux__ -#define _CRT_SECURE_NO_WARNINGS 1 -#endif - -#include - -#include "freetdm.h" -#include -#include -#include - - -/* arbitrary limit for max calls in this sample program */ -#define MAX_CALLS 255 - -/* some timers (in seconds) to fake responses in incoming calls */ -#define PROGRESS_TIMER 1 -#define ANSWER_TIMER 5 -#define HANGUP_TIMER 15 - -/* simple variable used to stop the application */ -static int app_running = 0; - -typedef void (*expired_function_t)(ftdm_channel_t *channel); -typedef struct dummy_timer_s { - int time; - ftdm_channel_t *channel; - expired_function_t expired; -} dummy_timer_t; - -/* dummy second resolution timers */ -static dummy_timer_t g_timers[MAX_CALLS]; - -/* mutex to protect the timers (both, the test thread and the signaling thread may modify them) */ -static ftdm_mutex_t *g_schedule_mutex; - -/* unique outgoing channel */ -static ftdm_channel_t *g_outgoing_channel = NULL; - -static void interrupt_requested(int signal) -{ - app_running = 0; -} - -static void schedule_timer(ftdm_channel_t *channel, int sec, expired_function_t expired) -{ - int i; - ftdm_mutex_lock(g_schedule_mutex); - for (i = 0; i < sizeof(g_timers)/sizeof(g_timers[0]); i++) { - /* check the timer slot is free to use */ - if (!g_timers[i].time) { - g_timers[i].time = sec; - g_timers[i].channel = channel; - g_timers[i].expired = expired; - ftdm_mutex_unlock(g_schedule_mutex); - return; - } - } - ftdm_log(FTDM_LOG_ERROR, "Failed to schedule timer\n"); - ftdm_mutex_unlock(g_schedule_mutex); -} - -static void run_timers(void) -{ - int i; - void *channel; - expired_function_t expired_func = NULL; - ftdm_mutex_lock(g_schedule_mutex); - for (i = 0; i < sizeof(g_timers)/sizeof(g_timers[0]); i++) { - /* if there's time left, decrement */ - if (g_timers[i].time) { - g_timers[i].time--; - } - - /* if time expired and we have an expired function, call it */ - if (!g_timers[i].time && g_timers[i].expired) { - expired_func = g_timers[i].expired; - channel = g_timers[i].channel; - memset(&g_timers[i], 0, sizeof(g_timers[i])); - expired_func(channel); - } - } - ftdm_mutex_unlock(g_schedule_mutex); -} - -static void release_timers(ftdm_channel_t *channel) -{ - int i; - ftdm_mutex_lock(g_schedule_mutex); - for (i = 0; i < sizeof(g_timers)/sizeof(g_timers[0]); i++) { - /* clear any timer belonging to the given channel */ - if (g_timers[i].channel == channel) { - memset(&g_timers[i], 0, sizeof(g_timers[i])); - } - } - ftdm_mutex_unlock(g_schedule_mutex); -} - -/* hangup the call */ -static void send_hangup(ftdm_channel_t *channel) -{ - int spanid = ftdm_channel_get_span_id(channel); - int chanid = ftdm_channel_get_id(channel); - ftdm_log(FTDM_LOG_NOTICE, "-- Requesting hangup in channel %d:%d\n", spanid, chanid); - ftdm_channel_call_hangup(channel); -} - -/* send answer for an incoming call */ -static void send_answer(ftdm_channel_t *channel) -{ - /* we move the channel signaling state machine to UP (answered) */ - int spanid = ftdm_channel_get_span_id(channel); - int chanid = ftdm_channel_get_id(channel); - ftdm_log(FTDM_LOG_NOTICE, "-- Requesting answer in channel %d:%d\n", spanid, chanid); - ftdm_channel_call_answer(channel); - schedule_timer(channel, HANGUP_TIMER, send_hangup); -} - -/* send progress for an incoming */ -static void send_progress(ftdm_channel_t *channel) -{ - /* we move the channel signaling state machine to UP (answered) */ - int spanid = ftdm_channel_get_span_id(channel); - int chanid = ftdm_channel_get_id(channel); - ftdm_log(FTDM_LOG_NOTICE, "-- Requesting progress\n", spanid, chanid); - ftdm_channel_call_indicate(channel, FTDM_CHANNEL_INDICATE_PROGRESS); - schedule_timer(channel, ANSWER_TIMER, send_answer); -} - -/* This function will be called in an undetermined signaling thread, you must not do - * any blocking operations here or the signaling stack may delay other call event processing - * The arguments for this function are defined in FIO_SIGNAL_CB_FUNCTION prototype, I just - * name them here for your convenience: - * ftdm_sigmsg_t *sigmsg - * - The sigmsg structure contains the ftdm_channel structure that represents the channel where - * the event occurred and the event_id of the signaling event that just occurred. - * */ -static FIO_SIGNAL_CB_FUNCTION(on_signaling_event) -{ - switch (sigmsg->event_id) { - /* This event signals the start of an incoming call */ - case FTDM_SIGEVENT_START: - ftdm_log(FTDM_LOG_NOTICE, "Incoming call received in channel %d:%d\n", sigmsg->span_id, sigmsg->chan_id); - schedule_timer(sigmsg->channel, PROGRESS_TIMER, send_progress); - break; - /* This event signals progress on an outgoing call */ - case FTDM_SIGEVENT_PROGRESS_MEDIA: - ftdm_log(FTDM_LOG_NOTICE, "Progress message received in channel %d:%d\n", sigmsg->span_id, sigmsg->chan_id); - break; - /* This event signals answer in an outgoing call */ - case FTDM_SIGEVENT_UP: - ftdm_log(FTDM_LOG_NOTICE, "Answer received in channel %d:%d\n", sigmsg->span_id, sigmsg->chan_id); - /* now the channel is answered and we can use - * ftdm_channel_wait() to wait for input/output in a channel (equivalent to poll() or select()) - * ftdm_channel_read() to read available data in a channel - * ftdm_channel_write() to write to the channel */ - break; - /* This event signals hangup from the other end */ - case FTDM_SIGEVENT_STOP: - ftdm_log(FTDM_LOG_NOTICE, "Hangup received in channel %d:%d\n", sigmsg->span_id, sigmsg->chan_id); - if (g_outgoing_channel == sigmsg->channel) { - g_outgoing_channel = NULL; - } - /* release any timer for this channel */ - release_timers(sigmsg->channel); - /* acknowledge the hangup */ - ftdm_channel_call_hangup(sigmsg->channel); - break; - default: - ftdm_log(FTDM_LOG_WARNING, "Unhandled event %s in channel %d:%d\n", ftdm_signal_event2str(sigmsg->event_id), - sigmsg->span_id, sigmsg->chan_id); - break; - } - return FTDM_SUCCESS; -} - -static void place_call(const ftdm_span_t *span, const char *number) -{ - ftdm_channel_t *ftdmchan = NULL; - ftdm_caller_data_t caller_data = {{ 0 }}; - ftdm_status_t status = FTDM_FAIL; - - /* set destiny number */ - ftdm_set_string(caller_data.dnis.digits, number); - - /* set callerid */ - ftdm_set_string(caller_data.cid_name, "testsangomaboost"); - ftdm_set_string(caller_data.cid_num.digits, "1234"); - - /* request to search for an outgoing channel top down with the given caller data. - * it is also an option to use ftdm_channel_open_by_group to let freetdm hunt - * an available channel in a given group instead of per span - * */ - status = ftdm_channel_open_by_span(ftdm_span_get_id(span), FTDM_TOP_DOWN, &caller_data, &ftdmchan); - if (status != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "Failed to originate call\n"); - return; - } - - g_outgoing_channel = ftdmchan; - - /* set the caller data for the outgoing channel */ - ftdm_channel_set_caller_data(ftdmchan, &caller_data); - - status = ftdm_channel_call_place(ftdmchan); - if (status != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "Failed to originate call\n"); - return; - } - - /* this is required to initialize the outgoing channel */ - ftdm_channel_init(ftdmchan); -} - -#define ARRLEN(arr) (sizeof(arr)/sizeof(arr[0])) -int main(int argc, char *argv[]) -{ - /* span names can be any null-terminated string, does not need to be a wanpipe port */ - int span_numbers[32]; - char span_names[ARRLEN(span_numbers)][ARRLEN(span_numbers)]; - const char *spanname = NULL; - char wpchans[25]; - unsigned configured = 0; - int i, spanno; - int numspans = 0; - ftdm_status_t status; - ftdm_span_t *span_list[ARRLEN(span_numbers)]; - ftdm_span_t *span; - ftdm_channel_config_t chan_config; - ftdm_conf_parameter_t parameters[20]; - char *todial = NULL; - int32_t ticks = 0; - - /* register a handler to shutdown things properly */ -#ifdef _WIN64 - // still trying to figure this one out otherwise triggers error - if (signal(SIGINT, interrupt_requested) < 0) { -#else - if (signal(SIGINT, interrupt_requested) == SIG_ERR) { -#endif - fprintf(stderr, "Could not set the SIGINT signal handler: %s\n", strerror(errno)); - exit(-1); - } - - for (i = 1; i < argc; i++) { - if (argv[i][0] == '-' && argv[i][1] == 'd') { - i++; - if (i >= argc) { - fprintf(stderr, "Error, -d specified but no number to dial!\n"); - exit(1); - } - todial = argv[i]; - if (!strlen(todial)) { - todial = NULL; - } - printf("Number to dial: %s\n", todial); - continue; - } - spanno = atoi(argv[i]); - span_numbers[numspans] = spanno; - snprintf(span_names[numspans], sizeof(span_names[numspans]), "wanpipe%d", spanno); - numspans++; - } - - if (!numspans) { - fprintf(stderr, "please specify a at least 1 wanpipe port number\n"); - exit(-1); - } - - /* clear any outstanding timers */ - memset(&g_timers, 0, sizeof(g_timers)); - - /* set the logging level to use */ - ftdm_global_set_default_logger(FTDM_LOG_LEVEL_DEBUG); - - /* Initialize the FTDM library */ - if (ftdm_global_init() != FTDM_SUCCESS) { - fprintf(stderr, "Error loading FreeTDM\n"); - exit(-1); - } - - /* create the schedule mutex */ - ftdm_mutex_create(&g_schedule_mutex); - - /* now we can start creating spans */ - memset(&chan_config, 0, sizeof(chan_config)); - strncpy(chan_config.group_name, "mygroup", sizeof(chan_config.group_name)-1); - chan_config.group_name[sizeof(chan_config.group_name)-1] = 0; - for (i = 0; i < numspans; i++) { - spanname = span_names[i]; - /* "wanpipe" is the special I/O identifier for Sangoma devices */ - ftdm_log(FTDM_LOG_NOTICE, "Creating span %s\n", spanname); - status = ftdm_span_create("wanpipe", spanname, &span_list[i]); - if (status != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_CRIT, "Failed to create span %s\n", spanname); - goto done; - } - span = span_list[i]; - spanno = span_numbers[i]; - - /* set the trunk type for the span */ - ftdm_span_set_trunk_type(span_list[i], FTDM_TRUNK_T1); - - /* configure B channels (syntax for wanpipe channels is span:low_chan-high_chan) */ - chan_config.type = FTDM_CHAN_TYPE_B; - snprintf(wpchans, sizeof(wpchans), "%d:1-23", spanno); - ftdm_configure_span_channels(span, wpchans, &chan_config, &configured); - ftdm_log(FTDM_LOG_NOTICE, "registered %d b channels\n", configured); - } - - /* At this point FreeTDM is ready to be used, the spans defined in freetdm.conf have the basic I/O board configuration - * but no telephony signaling configuration at all. */ - ftdm_log(FTDM_LOG_NOTICE, "FreeTDM loaded ...\n"); - - /* now we can start configuring signaling for the previously created spans */ - for (i = 0; i < numspans; i++) { - spanname = span_names[i]; - - /* Retrieve a span by name (as specified in ftdm_span_create()) */ - if (ftdm_span_find_by_name(spanname, &span) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "Error finding FreeTDM span %s\n", ftdm_span_get_name(span)); - goto done; - } - - /* prepare the configuration parameters that will be sent down to the signaling stack, the array of paramters must be terminated by an - * array element with a null .var member */ - - /* for sangoma_boost signaling (abstraction signaling used by Sangoma for PRI, BRI and SS7) the first parameter you must send - * is sigmod, which must be either sangoma_prid, if you have the PRI stack available, or sangoma_brid for the BRI stack */ - parameters[0].var = "sigmod"; - parameters[0].val = "sangoma_prid"; - - /* following parameters are signaling stack specific, this ones are for PRI */ - parameters[1].var = "switchtype"; - parameters[1].val = "national"; - - parameters[2].var = "signalling"; - parameters[2].val = "pri_cpe"; - - /* - * parameters[3].var = "nfas_primary"; - * parameters[3].val = "4"; //span number - * - * parameters[4].var = "nfas_secondary"; - * parameters[4].val = "2"; //span number - * - * parameters[5].var = "nfas_group"; - * parameters[5].val = "1"; - * */ - - - /* the last parameter .var member must be NULL! */ - parameters[3].var = NULL; - - /* send the configuration values down to the stack */ - if (ftdm_configure_span_signaling(span, "sangoma_boost", on_signaling_event, parameters) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "Error configuring sangoma_boost signaling abstraction in span %s\n", ftdm_span_get_name(span)); - goto done; - } - - } - - - /* configuration succeeded, we can proceed now to start each span - * This step will launch at least 1 background (may be more, depending on the signaling stack used) - * to handle *ALL* signaling events for this span, your on_signaling_event callback will be called always - * in one of those infraestructure threads and you MUST NOT block in that handler to avoid delays and errors - * in the signaling processing for any call. - * */ - for (i = 0; i < numspans; i++) { - spanname = span_names[i]; - /* Retrieve a span by name (as specified in ftdm_span_create()) */ - if (ftdm_span_find_by_name(spanname, &span) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "Error finding FreeTDM span %s\n", ftdm_span_get_name(span)); - goto done; - } - - if (ftdm_span_start(span) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "Failing starting signaling on span %s\n", ftdm_span_get_name(span)); - goto done; - } - - } - - app_running = 1; - - /* Retrieve the first created span to place the call (if dialing was specified) */ - if (ftdm_span_find(1, &span) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "Error finding FreeTDM span 1\n"); - goto done; - } - - /* The application thread can go on and do anything else, like waiting for a shutdown signal */ - while(ftdm_running() && app_running) { - ftdm_sleep(1000); - run_timers(); - ticks++; - if (!(ticks % 10) && todial && !g_outgoing_channel) { - ftdm_log(FTDM_LOG_NOTICE, "Originating call to number %s\n", todial); - place_call(span, todial); - } - } - - done: - - ftdm_log(FTDM_LOG_NOTICE, "Shutting down FreeTDM ...\n"); - - ftdm_mutex_destroy(&g_schedule_mutex); - - /* whenever you're done, this function will shutdown the signaling threads in any span that was started */ - ftdm_global_destroy(); - - printf("Terminated!\n"); - - sleep(2); - - exit(0); -} - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4: - */ diff --git a/libs/freetdm/src/ftdm_cpu_monitor.c b/libs/freetdm/src/ftdm_cpu_monitor.c index 4ebe353b57..b543f05210 100644 --- a/libs/freetdm/src/ftdm_cpu_monitor.c +++ b/libs/freetdm/src/ftdm_cpu_monitor.c @@ -37,8 +37,10 @@ */ #ifdef WIN32 -#define _WIN32_WINNT 0x0501 // To make GetSystemTimes visible in windows.h -#include +# if (_WIN32_WINNT < 0x0501) +# error "Need to target at least Windows XP/Server 2003 because GetSystemTimes is needed" +# endif +# include #else /* LINUX */ #include diff --git a/libs/freetdm/src/ftdm_dso.c b/libs/freetdm/src/ftdm_dso.c old mode 100644 new mode 100755 index 6e7403165d..5b33a44347 --- a/libs/freetdm/src/ftdm_dso.c +++ b/libs/freetdm/src/ftdm_dso.c @@ -122,5 +122,5 @@ FT_DECLARE(void *) ftdm_dso_func_sym(ftdm_dso_lib_t lib, const char *sym, char * * c-basic-offset:4 * End: * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 + * vim:set softtabstop=4 shiftwidth=4 tabstop=4: */ diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index cd2c4850a4..1951678d73 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -62,10 +62,11 @@ struct tm *localtime_r(const time_t *clock, struct tm *result); ftdm_time_t time_last_throttle_log = 0; ftdm_time_t time_current_throttle_log = 0; -static ftdm_iterator_t *get_iterator(ftdm_iterator_type_t type, ftdm_iterator_t *iter); static ftdm_status_t ftdm_call_set_call_id(ftdm_channel_t *fchan, ftdm_caller_data_t *caller_data); static ftdm_status_t ftdm_call_clear_call_id(ftdm_caller_data_t *caller_data); static ftdm_status_t ftdm_channel_done(ftdm_channel_t *ftdmchan); +static ftdm_status_t ftdm_channel_sig_indicate(ftdm_channel_t *ftdmchan, ftdm_channel_indication_t indication, ftdm_usrmsg_t *usrmsg); + static int time_is_init = 0; @@ -1899,10 +1900,9 @@ openchan: ftdm_set_flag(check, FTDM_CHANNEL_INUSE); ftdm_set_flag(check, FTDM_CHANNEL_OUTBOUND); *ftdmchan = check; -#if 1 + /* we've got the channel, do not unlock it */ goto done; -#endif unlockchan: ftdm_mutex_unlock(check->mutex); @@ -2063,25 +2063,25 @@ FT_DECLARE(ftdm_bool_t) ftdm_channel_call_check_done(const ftdm_channel_t *ftdmc return condition; } -FT_DECLARE(ftdm_status_t) _ftdm_channel_call_hold(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan) +FT_DECLARE(ftdm_status_t) _ftdm_channel_call_hold(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_usrmsg_t *usrmsg) { ftdm_status_t status; ftdm_channel_lock(ftdmchan); ftdm_set_flag(ftdmchan, FTDM_CHANNEL_HOLD); - status = ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_DIALTONE, 0); + status = ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_DIALTONE, 0, usrmsg); ftdm_channel_unlock(ftdmchan); return status; } -FT_DECLARE(ftdm_status_t) _ftdm_channel_call_unhold(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan) +FT_DECLARE(ftdm_status_t) _ftdm_channel_call_unhold(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_usrmsg_t *usrmsg) { ftdm_status_t status; ftdm_channel_lock(ftdmchan); - status = ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_UP, 0); + status = ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_UP, 0, usrmsg); ftdm_channel_unlock(ftdmchan); @@ -2108,7 +2108,7 @@ FT_DECLARE(void) ftdm_ack_indication(ftdm_channel_t *fchan, ftdm_channel_indicat } /*! Answer call without locking the channel. The caller must have locked first */ -static ftdm_status_t _ftdm_channel_call_answer_nl(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan) +static ftdm_status_t _ftdm_channel_call_answer_nl(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_usrmsg_t *usrmsg) { ftdm_status_t status = FTDM_SUCCESS; @@ -2118,7 +2118,7 @@ static ftdm_status_t _ftdm_channel_call_answer_nl(const char *file, const char * * use FTDM_SPAN_USE_SKIP_STATES for now while we update the sig modules */ if (ftdmchan->state < FTDM_CHANNEL_STATE_PROGRESS) { - status = ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS, 1); + status = ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS, 1, usrmsg); if (status != FTDM_SUCCESS) { status = FTDM_ECANCELED; goto done; @@ -2133,7 +2133,7 @@ static ftdm_status_t _ftdm_channel_call_answer_nl(const char *file, const char * } if (ftdmchan->state < FTDM_CHANNEL_STATE_PROGRESS_MEDIA) { - status = ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, 1); + status = ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, 1, usrmsg); if (status != FTDM_SUCCESS) { status = FTDM_ECANCELED; goto done; @@ -2148,7 +2148,7 @@ static ftdm_status_t _ftdm_channel_call_answer_nl(const char *file, const char * } } - status = ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_UP, 1); + status = ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_UP, 1, usrmsg); if (status != FTDM_SUCCESS) { status = FTDM_ECANCELED; goto done; @@ -2159,19 +2159,19 @@ done: return status; } -FT_DECLARE(ftdm_status_t) _ftdm_channel_call_answer(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan) +FT_DECLARE(ftdm_status_t) _ftdm_channel_call_answer(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_usrmsg_t *usrmsg) { ftdm_status_t status; /* we leave the locking up to ftdm_channel_call_indicate, DO NOT lock here since ftdm_channel_call_indicate expects * the lock recursivity to be 1 */ - status = _ftdm_channel_call_indicate(file, func, line, ftdmchan, FTDM_CHANNEL_INDICATE_ANSWER); + status = _ftdm_channel_call_indicate(file, func, line, ftdmchan, FTDM_CHANNEL_INDICATE_ANSWER, usrmsg); return status; } /* lock must be acquired by the caller! */ -static ftdm_status_t _ftdm_channel_call_hangup_nl(const char *file, const char *func, int line, ftdm_channel_t *chan) +static ftdm_status_t _ftdm_channel_call_hangup_nl(const char *file, const char *func, int line, ftdm_channel_t *chan, ftdm_usrmsg_t *usrmsg) { ftdm_status_t status = FTDM_SUCCESS; @@ -2188,7 +2188,7 @@ static ftdm_status_t _ftdm_channel_call_hangup_nl(const char *file, const char * if (ftdm_test_flag(chan, FTDM_CHANNEL_STATE_CHANGE)) { ftdm_channel_cancel_state(file, func, line, chan); } - status = ftdm_channel_set_state(file, func, line, chan, FTDM_CHANNEL_STATE_HANGUP, 1); + status = ftdm_channel_set_state(file, func, line, chan, FTDM_CHANNEL_STATE_HANGUP, 1, usrmsg); } else { /* the signaling stack did not touch the state, * core is responsible from clearing flags and stuff, however, because ftmod_analog @@ -2204,20 +2204,20 @@ static ftdm_status_t _ftdm_channel_call_hangup_nl(const char *file, const char * return status; } -FT_DECLARE(ftdm_status_t) _ftdm_channel_call_hangup_with_cause(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_call_cause_t cause) +FT_DECLARE(ftdm_status_t) _ftdm_channel_call_hangup_with_cause(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_call_cause_t cause, ftdm_usrmsg_t *usrmsg) { ftdm_status_t status = FTDM_SUCCESS; ftdm_channel_lock(ftdmchan); ftdmchan->caller_data.hangup_cause = cause; - status = _ftdm_channel_call_hangup_nl(file, func, line, ftdmchan); + status = _ftdm_channel_call_hangup_nl(file, func, line, ftdmchan, usrmsg); ftdm_channel_unlock(ftdmchan); return status; } -FT_DECLARE(ftdm_status_t) _ftdm_channel_call_hangup(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan) +FT_DECLARE(ftdm_status_t) _ftdm_channel_call_hangup(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_usrmsg_t *usrmsg) { ftdm_status_t status = FTDM_SUCCESS; @@ -2225,7 +2225,7 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_hangup(const char *file, const char ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_CLEARING; - status = _ftdm_channel_call_hangup_nl(file, func, line, ftdmchan); + status = _ftdm_channel_call_hangup_nl(file, func, line, ftdmchan, usrmsg); ftdm_channel_unlock(ftdmchan); return status; @@ -2285,7 +2285,7 @@ FT_DECLARE(uint32_t) ftdm_channel_get_ph_span_id(const ftdm_channel_t *ftdmchan) * someone *MUST* acknowledge the indication, either the signaling stack, this function or the core * at some later point * */ -FT_DECLARE(ftdm_status_t) _ftdm_channel_call_indicate(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_channel_indication_t indication) +FT_DECLARE(ftdm_status_t) _ftdm_channel_call_indicate(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_channel_indication_t indication, ftdm_usrmsg_t *usrmsg) { ftdm_status_t status = FTDM_SUCCESS; @@ -2328,26 +2328,26 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_indicate(const char *file, const ch /* FIXME: ring and busy cannot be used with all signaling stacks * (particularly isdn stacks I think, we should emulate or just move to hangup with busy cause) */ case FTDM_CHANNEL_INDICATE_RINGING: - status = ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_RINGING, 1); + status = ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_RINGING, 1, usrmsg); break; case FTDM_CHANNEL_INDICATE_BUSY: - status = ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_BUSY, 1); + status = ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_BUSY, 1, usrmsg); break; case FTDM_CHANNEL_INDICATE_PROCEED: if (!ftdm_test_flag(ftdmchan->span, FTDM_SPAN_USE_PROCEED_STATE) || - ftdmchan->state == FTDM_CHANNEL_STATE_PROCEED) { + ftdmchan->state >= FTDM_CHANNEL_STATE_PROCEED) { ftdm_ack_indication(ftdmchan, indication, status); goto done; } - status = ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROCEED, 1); + status = ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROCEED, 1, usrmsg); break; case FTDM_CHANNEL_INDICATE_PROGRESS: - status = ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS, 1); + status = ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS, 1, usrmsg); break; case FTDM_CHANNEL_INDICATE_PROGRESS_MEDIA: if (!ftdm_test_flag(ftdmchan->span, FTDM_SPAN_USE_SKIP_STATES)) { if (ftdmchan->state < FTDM_CHANNEL_STATE_PROGRESS) { - status = ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS, 1); + status = ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS, 1, usrmsg); if (status != FTDM_SUCCESS) { goto done; } @@ -2359,14 +2359,14 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_indicate(const char *file, const ch goto done; } } - status = ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, 1); + status = ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, 1, usrmsg); break; case FTDM_CHANNEL_INDICATE_ANSWER: - status = _ftdm_channel_call_answer_nl(file, func, line, ftdmchan); + status = _ftdm_channel_call_answer_nl(file, func, line, ftdmchan, usrmsg); break; default: - ftdm_log(file, func, line, FTDM_LOG_LEVEL_WARNING, "Do not know how to indicate %d\n", indication); - status = FTDM_EINVAL; + /* See if signalling module can provide this indication */ + status = ftdm_channel_sig_indicate(ftdmchan, indication, usrmsg); break; } @@ -2376,38 +2376,19 @@ done: return status; } -FT_DECLARE(ftdm_status_t) _ftdm_channel_call_send_msg(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_sigmsg_t *sigmsg) -{ - ftdm_status_t status = FTDM_FAIL; - ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "null channel"); -#ifdef __WINDOWS__ - UNREFERENCED_PARAMETER(file); - UNREFERENCED_PARAMETER(func); - UNREFERENCED_PARAMETER(line); -#endif - - ftdm_channel_lock(ftdmchan); - if (ftdmchan->span->send_msg) { - status = ftdmchan->span->send_msg(ftdmchan, sigmsg); - } else { - status = FTDM_NOTIMPL; - ftdm_log(FTDM_LOG_ERROR, "send_msg method not implemented in this span!\n"); - } - ftdm_channel_unlock(ftdmchan); - return status; -} - -FT_DECLARE(ftdm_status_t) _ftdm_channel_reset(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan) +FT_DECLARE(ftdm_status_t) _ftdm_channel_reset(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_usrmsg_t *usrmsg) { ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "null channel"); ftdm_channel_lock(ftdmchan); - ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_RESET, 1); + ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_RESET, 1, usrmsg); ftdm_channel_unlock(ftdmchan); return FTDM_SUCCESS; } -static ftdm_status_t _ftdm_channel_call_place_nl(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan) +/* this function MUST be called with the channel lock held with lock recursivity of 1 exactly, + * and the caller must be aware we might unlock the channel for a brief period of time and then lock it again */ +static ftdm_status_t _ftdm_channel_call_place_nl(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_usrmsg_t *usrmsg) { ftdm_status_t status = FTDM_FAIL; @@ -2430,11 +2411,6 @@ static ftdm_status_t _ftdm_channel_call_place_nl(const char *file, const char *f goto done; } - if (ftdmchan->state != FTDM_CHANNEL_STATE_DOWN) { - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Cannot place call in channel in state %s!\n", ftdm_channel_state2str(ftdmchan->state)); - goto done; - } - status = ftdmchan->span->outgoing_call(ftdmchan); if (status == FTDM_BREAK) { /* the signaling module detected glare on time */ @@ -2447,13 +2423,24 @@ static ftdm_status_t _ftdm_channel_call_place_nl(const char *file, const char *f goto done; } - /* in case of success, *before* unlocking the channel, we must set the call started flag and the call id - * that is a guarantee that signaling modules expect from us */ ftdm_set_flag(ftdmchan, FTDM_CHANNEL_CALL_STARTED); ftdm_call_set_call_id(ftdmchan, &ftdmchan->caller_data); - if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_NONBLOCK)) { - /* be aware this waiting unlocks the channel and locks it back when done */ - ftdm_wait_for_flag_cleared(ftdmchan, FTDM_CHANNEL_STATE_CHANGE, 100); + + /* if the signaling stack left the channel in state down on success, is expecting us to move to DIALING */ + if (ftdmchan->state == FTDM_CHANNEL_STATE_DOWN) { + if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_NONBLOCK)) { + ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_DIALING, 1, usrmsg); + } else { + ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_DIALING, 0, usrmsg); + } + } else if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE) && + !ftdm_test_flag(ftdmchan, FTDM_CHANNEL_NONBLOCK)) { + + ftdm_channel_unlock(ftdmchan); + + ftdm_interrupt_wait(ftdmchan->state_completed_interrupt, 500); + + ftdm_channel_lock(ftdmchan); } done: @@ -2465,19 +2452,20 @@ done: return status; } -FT_DECLARE(ftdm_status_t) _ftdm_channel_call_place(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan) +FT_DECLARE(ftdm_status_t) _ftdm_channel_call_place(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_usrmsg_t *usrmsg) { ftdm_status_t status; ftdm_channel_lock(ftdmchan); - status = _ftdm_channel_call_place_nl(file, func, line, ftdmchan); + /* be aware that _ftdm_channl_call_place_nl can unlock/lock the channel quickly if working in blocking mode */ + status = _ftdm_channel_call_place_nl(file, func, line, ftdmchan, usrmsg); ftdm_channel_unlock(ftdmchan); return status; } FT_DECLARE(ftdm_status_t) _ftdm_call_place(const char *file, const char *func, int line, - ftdm_caller_data_t *caller_data, ftdm_hunting_scheme_t *hunting) + ftdm_caller_data_t *caller_data, ftdm_hunting_scheme_t *hunting, ftdm_usrmsg_t *usrmsg) { ftdm_status_t status = FTDM_SUCCESS; ftdm_channel_t *fchan = NULL; @@ -2513,9 +2501,10 @@ FT_DECLARE(ftdm_status_t) _ftdm_call_place(const char *file, const char *func, i ftdm_channel_set_caller_data(fchan, caller_data); - status = _ftdm_channel_call_place_nl(file, func, line, fchan); + /* be aware that _ftdm_channl_call_place_nl can unlock/lock the channel quickly if working in blocking mode */ + status = _ftdm_channel_call_place_nl(file, func, line, fchan, usrmsg); if (status != FTDM_SUCCESS) { - _ftdm_channel_call_hangup_nl(file, func, line, fchan); + _ftdm_channel_call_hangup_nl(file, func, line, fchan, usrmsg); goto done; } @@ -2603,6 +2592,29 @@ FT_DECLARE(ftdm_status_t) ftdm_span_get_sig_status(ftdm_span_t *span, ftdm_signa } } +static ftdm_status_t ftdm_channel_sig_indicate(ftdm_channel_t *ftdmchan, ftdm_channel_indication_t indication, ftdm_usrmsg_t *usrmsg) +{ + ftdm_status_t status = FTDM_FAIL; + if (ftdmchan->span->indicate) { + + ftdm_channel_save_usrmsg(ftdmchan, usrmsg); + + status = ftdmchan->span->indicate(ftdmchan, indication); + if (status == FTDM_NOTIMPL) { + ftdm_log(FTDM_LOG_WARNING, "Do not know how to indicate %s\n", ftdm_channel_indication2str(indication)); + } else if (status != FTDM_SUCCESS) { + ftdm_log(FTDM_LOG_WARNING, "Failed to indicate %s\n", ftdm_channel_indication2str(indication)); + } else { /* SUCCESS */ + ftdm_ack_indication(ftdmchan, indication, FTDM_SUCCESS); + } + ftdm_usrmsg_free(&ftdmchan->usrmsg); + } else { + return FTDM_NOTIMPL; + } + return status; +} + + /* this function must be called with the channel lock */ static ftdm_status_t ftdm_channel_done(ftdm_channel_t *ftdmchan) { @@ -2630,6 +2642,7 @@ static ftdm_status_t ftdm_channel_done(ftdm_channel_t *ftdmchan) ftdm_buffer_destroy(&ftdmchan->pre_buffer); ftdmchan->pre_buffer_size = 0; ftdm_mutex_unlock(ftdmchan->pre_buffer_mutex); + if (ftdmchan->hangup_timer) { ftdm_sched_cancel_timer(globals.timingsched, ftdmchan->hangup_timer); } @@ -3504,7 +3517,8 @@ skipdebug: ftdmchan->dtmf_hangup_buf[ftdmchan->span->dtmf_hangup_len - 1] = *p; if (!strcmp(ftdmchan->dtmf_hangup_buf, ftdmchan->span->dtmf_hangup)) { ftdm_log(FTDM_LOG_DEBUG, "DTMF hangup detected.\n"); - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); + + ftdm_channel_set_state(__FILE__, __FUNCTION__, __LINE__, ftdmchan, FTDM_CHANNEL_STATE_HANGUP, 0, NULL); break; } } @@ -4028,92 +4042,7 @@ done: return status; } -FT_DECLARE(void) ftdm_call_clear_data(ftdm_caller_data_t *caller_data) -{ - if (caller_data->variables) { - hashtable_destroy(caller_data->variables); - } - caller_data->variables = NULL; - memset(&caller_data->raw_data, 0, sizeof(caller_data->raw_data)); - caller_data->raw_data_len = 0; -} - -FT_DECLARE(ftdm_status_t) ftdm_call_remove_var(ftdm_caller_data_t *caller_data, const char *var_name) -{ - if (caller_data->variables) { - hashtable_remove(caller_data->variables, (void *)var_name); - } - - return FTDM_SUCCESS; -} - -FT_DECLARE(ftdm_status_t) ftdm_call_add_var(ftdm_caller_data_t *caller_data, const char *var_name, const char *value) -{ - char *t_name = 0, *t_val = 0; - - if (!var_name || !value) { - return FTDM_FAIL; - } - - if (!caller_data->variables) { - /* initialize on first use */ - caller_data->variables = create_hashtable(16, ftdm_hash_hashfromstring, ftdm_hash_equalkeys); - ftdm_assert_return(caller_data->variables, FTDM_FAIL, "Failed to create hash table\n"); - } - - t_name = ftdm_strdup(var_name); - t_val = ftdm_strdup(value); - hashtable_insert(caller_data->variables, t_name, t_val, HASHTABLE_FLAG_FREE_KEY | HASHTABLE_FLAG_FREE_VALUE); - return FTDM_SUCCESS; -} - -FT_DECLARE(const char *) ftdm_call_get_var(ftdm_caller_data_t *caller_data, const char *var_name) -{ - const char *var = NULL; - - if (!caller_data->variables || !var_name) { - return NULL; - } - - var = (const char *)hashtable_search(((struct hashtable*)caller_data->variables), (void *)var_name); - return var; -} - -FT_DECLARE(ftdm_iterator_t *) ftdm_call_get_var_iterator(const ftdm_caller_data_t *caller_data, ftdm_iterator_t *iter) -{ - ftdm_hash_iterator_t *hashiter = NULL; - hashiter = caller_data->variables == NULL ? NULL : hashtable_first(caller_data->variables); - - if (hashiter == NULL) { - return NULL; - } - - if (!(iter = get_iterator(FTDM_ITERATOR_VARS, iter))) { - return NULL; - } - iter->pvt.hashiter = hashiter; - return iter; -} - -FT_DECLARE(ftdm_status_t) ftdm_call_get_current_var(ftdm_iterator_t *iter, const char **var_name, const char **var_val) -{ - const void *key = NULL; - void *val = NULL; - - *var_name = NULL; - *var_val = NULL; - - ftdm_assert_return(iter && (iter->type == FTDM_ITERATOR_VARS) && iter->pvt.hashiter, FTDM_FAIL, "Cannot get variable from invalid iterator!\n"); - - hashtable_this(iter->pvt.hashiter, &key, NULL, &val); - - *var_name = key; - *var_val = val; - - return FTDM_SUCCESS; -} - -static ftdm_iterator_t *get_iterator(ftdm_iterator_type_t type, ftdm_iterator_t *iter) +FT_DECLARE(ftdm_iterator_t *) ftdm_get_iterator(ftdm_iterator_type_t type, ftdm_iterator_t *iter) { int allocated = 0; if (iter) { @@ -4139,7 +4068,7 @@ static ftdm_iterator_t *get_iterator(ftdm_iterator_type_t type, ftdm_iterator_t FT_DECLARE(ftdm_iterator_t *) ftdm_span_get_chan_iterator(const ftdm_span_t *span, ftdm_iterator_t *iter) { - if (!(iter = get_iterator(FTDM_ITERATOR_CHANS, iter))) { + if (!(iter = ftdm_get_iterator(FTDM_ITERATOR_CHANS, iter))) { return NULL; } iter->pvt.chaniter.index = 1; @@ -5360,14 +5289,6 @@ FT_DECLARE(ftdm_status_t) ftdm_group_create(ftdm_group_t **group, const char *na static ftdm_status_t ftdm_span_trigger_signal(const ftdm_span_t *span, ftdm_sigmsg_t *sigmsg) { ftdm_status_t status = span->signal_cb(sigmsg); - if (sigmsg->channel) { - ftdm_call_clear_data(&(sigmsg->channel->caller_data)); - } - if (sigmsg->raw.autofree) { - ftdm_safe_free(sigmsg->raw.data); - sigmsg->raw.data = NULL; - sigmsg->raw.len = 0; - } return status; } @@ -5390,7 +5311,7 @@ FT_DECLARE(ftdm_status_t) ftdm_span_trigger_signals(const ftdm_span_t *span) ftdm_sigmsg_t *sigmsg = NULL; while ((sigmsg = ftdm_queue_dequeue(span->pendingsignals))) { ftdm_span_trigger_signal(span, sigmsg); - ftdm_safe_free(sigmsg); + ftdm_sigmsg_free(&sigmsg); } return FTDM_SUCCESS; } @@ -5403,7 +5324,7 @@ static void execute_safety_hangup(void *data) fchan->hangup_timer = 0; if (fchan->state == FTDM_CHANNEL_STATE_TERMINATING) { ftdm_log_chan(fchan, FTDM_LOG_CRIT, "Forcing hangup since the user did not confirmed our hangup after %dms\n", FORCE_HANGUP_TIMER); - _ftdm_channel_call_hangup_nl(__FILE__, __FUNCTION__, __LINE__, fchan); + _ftdm_channel_call_hangup_nl(__FILE__, __FUNCTION__, __LINE__, fchan, NULL); } else { ftdm_log_chan(fchan, FTDM_LOG_CRIT, "Not performing safety hangup, channel state is %s\n", ftdm_channel_state2str(fchan->state)); } @@ -5616,17 +5537,30 @@ FT_DECLARE(ftdm_status_t) ftdm_global_init(void) ftdm_mutex_create(&globals.call_id_mutex); ftdm_sched_global_init(); + globals.running = 1; if (ftdm_sched_create(&globals.timingsched, "freetdm-master") != FTDM_SUCCESS) { ftdm_log(FTDM_LOG_CRIT, "Failed to create master timing schedule context\n"); - return FTDM_FAIL; + goto global_init_fail; } if (ftdm_sched_free_run(globals.timingsched) != FTDM_SUCCESS) { ftdm_log(FTDM_LOG_CRIT, "Failed to run master timing schedule context\n"); - return FTDM_FAIL; + goto global_init_fail; } - - globals.running = 1; + return FTDM_SUCCESS; + +global_init_fail: + globals.running = 0; + ftdm_mutex_destroy(&globals.mutex); + ftdm_mutex_destroy(&globals.span_mutex); + ftdm_mutex_destroy(&globals.group_mutex); + ftdm_mutex_destroy(&globals.call_id_mutex); + hashtable_destroy(globals.interface_hash); + hashtable_destroy(globals.module_hash); + hashtable_destroy(globals.span_hash); + hashtable_destroy(globals.group_hash); + + return FTDM_FAIL; } FT_DECLARE(ftdm_status_t) ftdm_global_configuration(void) @@ -6106,6 +6040,123 @@ static ftdm_status_t ftdm_call_clear_call_id(ftdm_caller_data_t *caller_data) return FTDM_SUCCESS; } +FT_DECLARE(ftdm_status_t) ftdm_sigmsg_get_raw_data(ftdm_sigmsg_t *sigmsg, void **data, ftdm_size_t *datalen) +{ + if (!sigmsg || !sigmsg->raw.len) { + return FTDM_FAIL; + } + + *data = sigmsg->raw.data; + *datalen = sigmsg->raw.len; + + return FTDM_SUCCESS; +} + +FT_DECLARE(ftdm_status_t) ftdm_sigmsg_get_raw_data_detached(ftdm_sigmsg_t *sigmsg, void **data, ftdm_size_t *datalen) +{ + if (!sigmsg || !sigmsg->raw.len) { + return FTDM_FAIL; + } + + *data = sigmsg->raw.data; + *datalen = sigmsg->raw.len; + return FTDM_SUCCESS; +} + +FT_DECLARE(ftdm_status_t) ftdm_sigmsg_set_raw_data(ftdm_sigmsg_t *sigmsg, void *data, ftdm_size_t datalen) +{ + ftdm_assert_return(sigmsg, FTDM_FAIL, "Trying to set raw data on a NULL event\n"); + ftdm_assert_return(!sigmsg->raw.len, FTDM_FAIL, "Overwriting existing raw data\n"); + ftdm_assert_return(datalen, FTDM_FAIL, "Data length not set\n"); + + sigmsg->raw.data = data; + sigmsg->raw.len = datalen; + return FTDM_SUCCESS; +} + +FT_DECLARE(ftdm_status_t) ftdm_usrmsg_get_raw_data(ftdm_usrmsg_t *usrmsg, void **data, ftdm_size_t *datalen) +{ + if (!usrmsg || !usrmsg->raw.len) { + return FTDM_FAIL; + } + + *data = usrmsg->raw.data; + *datalen = usrmsg->raw.len; + + return FTDM_SUCCESS; +} + +FT_DECLARE(ftdm_status_t) ftdm_usrmsg_set_raw_data(ftdm_usrmsg_t *usrmsg, void *data, ftdm_size_t datalen) +{ + ftdm_assert_return(usrmsg, FTDM_FAIL, "Trying to set raw data on a NULL event\n"); + ftdm_assert_return(!usrmsg->raw.len, FTDM_FAIL, "Overwriting existing raw data\n"); + ftdm_assert_return(datalen, FTDM_FAIL, "Data length not set\n"); + + usrmsg->raw.data = data; + usrmsg->raw.len = datalen; + return FTDM_SUCCESS; +} + +FT_DECLARE(ftdm_status_t) ftdm_channel_save_usrmsg(ftdm_channel_t *ftdmchan, ftdm_usrmsg_t *usrmsg) +{ + ftdm_assert_return(!ftdmchan->usrmsg, FTDM_FAIL, "Info from previous event was not cleared\n"); + if (usrmsg) { + /* Copy sigmsg from user to internal copy so user can set new variables without race condition */ + ftdmchan->usrmsg = ftdm_calloc(1, sizeof(ftdm_usrmsg_t)); + memcpy(ftdmchan->usrmsg, usrmsg, sizeof(ftdm_usrmsg_t)); + + if (usrmsg->raw.data) { + usrmsg->raw.data = NULL; + usrmsg->raw.len = 0; + } + if (usrmsg->variables) { + usrmsg->variables = NULL; + } + } + return FTDM_SUCCESS; +} + +FT_DECLARE(ftdm_status_t) ftdm_sigmsg_free(ftdm_sigmsg_t **sigmsg) +{ + if (!*sigmsg) { + return FTDM_SUCCESS; + } + + if ((*sigmsg)->variables) { + hashtable_destroy((*sigmsg)->variables); + (*sigmsg)->variables = NULL; + } + + if ((*sigmsg)->raw.data) { + ftdm_safe_free((*sigmsg)->raw.data); + (*sigmsg)->raw.data = NULL; + (*sigmsg)->raw.len = 0; + } + + ftdm_safe_free(*sigmsg); + return FTDM_SUCCESS; +} + +FT_DECLARE(ftdm_status_t) ftdm_usrmsg_free(ftdm_usrmsg_t **usrmsg) +{ + if (!*usrmsg) { + return FTDM_SUCCESS; + } + + if ((*usrmsg)->variables) { + hashtable_destroy((*usrmsg)->variables); + (*usrmsg)->variables = NULL; + } + + if ((*usrmsg)->raw.data) { + ftdm_safe_free((*usrmsg)->raw.data); + (*usrmsg)->raw.data = NULL; + (*usrmsg)->raw.len = 0; + } + + ftdm_safe_free(*usrmsg); + return FTDM_SUCCESS; +} diff --git a/libs/freetdm/src/ftdm_state.c b/libs/freetdm/src/ftdm_state.c index 9fe2b911dc..54ecde530d 100644 --- a/libs/freetdm/src/ftdm_state.c +++ b/libs/freetdm/src/ftdm_state.c @@ -40,19 +40,7 @@ FTDM_STR2ENUM(ftdm_str2ftdm_channel_state, ftdm_channel_state2str, ftdm_channel_ FTDM_ENUM_NAMES(CHANNEL_STATE_STATUS_NAMES, CHANNEL_STATE_STATUS_STRINGS) FTDM_STR2ENUM(ftdm_str2ftdm_state_status, ftdm_state_status2str, ftdm_state_status_t, CHANNEL_STATE_STATUS_NAMES, FTDM_STATE_STATUS_INVALID) -/* This function is only needed for boost and we should get rid of it at the next refactoring */ -FT_DECLARE(ftdm_status_t) ftdm_channel_init(ftdm_channel_t *fchan) -{ - ftdm_channel_lock(fchan); - - if (fchan->init_state != FTDM_CHANNEL_STATE_DOWN) { - ftdm_channel_set_state(__FILE__, __FUNCTION__, __LINE__, fchan, fchan->init_state, 1); - fchan->init_state = FTDM_CHANNEL_STATE_DOWN; - } - - ftdm_channel_unlock(fchan); - return FTDM_SUCCESS; -} +static ftdm_status_t ftdm_core_set_state(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_channel_state_t state, int waitrq); FT_DECLARE(ftdm_status_t) _ftdm_channel_complete_state(const char *file, const char *func, int line, ftdm_channel_t *fchan) { @@ -66,6 +54,8 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_complete_state(const char *file, const c return FTDM_SUCCESS; } + ftdm_usrmsg_free(&fchan->usrmsg); + ftdm_clear_flag(fchan, FTDM_CHANNEL_STATE_CHANGE); if (state == FTDM_CHANNEL_STATE_PROGRESS) { @@ -123,7 +113,7 @@ FT_DECLARE(ftdm_status_t) _ftdm_set_state(const char *file, const char *func, in the current state */ _ftdm_channel_complete_state(file, func, line, fchan); } - return ftdm_channel_set_state(file, func, line, fchan, state, 0); + return ftdm_core_set_state(file, func, line, fchan, state, 0); } static int ftdm_parse_state_map(ftdm_channel_t *ftdmchan, ftdm_channel_state_t state, ftdm_state_map_t *state_map) @@ -225,9 +215,20 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_cancel_state(const char *file, const char return FTDM_SUCCESS; } + +FT_DECLARE(ftdm_status_t) ftdm_channel_set_state(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_channel_state_t state, int waitrq, ftdm_usrmsg_t *usrmsg) +{ + ftdm_channel_save_usrmsg(ftdmchan, usrmsg); + + if (ftdm_core_set_state(file, func, line, ftdmchan, state, waitrq) != FTDM_SUCCESS) { + ftdm_usrmsg_free(&ftdmchan->usrmsg); + } + return FTDM_SUCCESS; +} + /* this function MUST be called with the channel lock held. If waitrq == 1, the channel will be unlocked/locked (never call it with waitrq == 1 with an lock recursivity > 1) */ #define DEFAULT_WAIT_TIME 1000 -FT_DECLARE(ftdm_status_t) ftdm_channel_set_state(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_channel_state_t state, int waitrq) +static ftdm_status_t ftdm_core_set_state(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_channel_state_t state, int waitrq) { ftdm_status_t status; int ok = 1; @@ -515,7 +516,7 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_advance_states(ftdm_channel_t *fchan) * already completed implicitly by the state_processor() function via some internal * call to ftdm_set_state() */ fchan->state_status = FTDM_STATE_STATUS_PROCESSED; - } + } } return FTDM_SUCCESS; diff --git a/libs/freetdm/src/ftdm_threadmutex.c b/libs/freetdm/src/ftdm_threadmutex.c index 6efa27714c..57a8fb4830 100644 --- a/libs/freetdm/src/ftdm_threadmutex.c +++ b/libs/freetdm/src/ftdm_threadmutex.c @@ -22,8 +22,10 @@ */ #ifdef WIN32 -/* required for TryEnterCriticalSection definition. Must be defined before windows.h include */ -#define _WIN32_WINNT 0x0400 +# if (_WIN32_WINNT < 0x0400) +# error "Need to target at least Windows 95/WINNT 4.0 because TryEnterCriticalSection is needed" +# endif +# include #endif #include "private/ftdm_core.h" diff --git a/libs/freetdm/src/ftdm_variables.c b/libs/freetdm/src/ftdm_variables.c new file mode 100644 index 0000000000..a2899c4ca9 --- /dev/null +++ b/libs/freetdm/src/ftdm_variables.c @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2010, Sangoma Technologies + * David Yat Sin + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of the original author; nor the names of any contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Contributors: + * + * Moises Silva + * + */ + +#include "private/ftdm_core.h" + +FT_DECLARE(ftdm_status_t) ftdm_sigmsg_add_var(ftdm_sigmsg_t *sigmsg, const char *var_name, const char *value) +{ + char *t_name = 0, *t_val = 0; + + if (!sigmsg || !var_name || !value) { + return FTDM_FAIL; + } + + if (!sigmsg->variables) { + /* initialize on first use */ + sigmsg->variables = create_hashtable(16, ftdm_hash_hashfromstring, ftdm_hash_equalkeys); + ftdm_assert_return(sigmsg->variables, FTDM_FAIL, "Failed to create hash table\n"); + } + + t_name = ftdm_strdup(var_name); + t_val = ftdm_strdup(value); + hashtable_insert(sigmsg->variables, t_name, t_val, HASHTABLE_FLAG_FREE_KEY | HASHTABLE_FLAG_FREE_VALUE); + return FTDM_SUCCESS; +} + +FT_DECLARE(ftdm_status_t) ftdm_sigmsg_remove_var(ftdm_sigmsg_t *sigmsg, const char *var_name) +{ + if (sigmsg && sigmsg->variables) { + hashtable_remove(sigmsg->variables, (void *)var_name); + } + return FTDM_SUCCESS; +} + +FT_DECLARE(const char *) ftdm_sigmsg_get_var(ftdm_sigmsg_t *sigmsg, const char *var_name) +{ + const char *var = NULL; + + if (!sigmsg || !sigmsg->variables || !var_name) { + return NULL; + } + + var = (const char *)hashtable_search(((struct hashtable*)sigmsg->variables), (void *)var_name); + return var; +} + +FT_DECLARE(ftdm_iterator_t *) ftdm_sigmsg_get_var_iterator(const ftdm_sigmsg_t *sigmsg, ftdm_iterator_t *iter) +{ + ftdm_hash_iterator_t *hashiter = NULL; + if (!sigmsg) { + return NULL; + } + + hashiter = sigmsg->variables == NULL ? NULL : hashtable_first(sigmsg->variables); + + if (hashiter == NULL) { + return NULL; + } + + if (!(iter = ftdm_get_iterator(FTDM_ITERATOR_VARS, iter))) { + return NULL; + } + iter->pvt.hashiter = hashiter; + return iter; +} + +FT_DECLARE(ftdm_status_t) ftdm_get_current_var(ftdm_iterator_t *iter, const char **var_name, const char **var_val) +{ + const void *key = NULL; + void *val = NULL; + + *var_name = NULL; + *var_val = NULL; + + ftdm_assert_return(iter && (iter->type == FTDM_ITERATOR_VARS) && iter->pvt.hashiter, FTDM_FAIL, "Cannot get variable from invalid iterator!\n"); + + hashtable_this(iter->pvt.hashiter, &key, NULL, &val); + + *var_name = key; + *var_val = val; + + return FTDM_SUCCESS; +} + + +FT_DECLARE(ftdm_status_t) ftdm_usrmsg_add_var(ftdm_usrmsg_t *usrmsg, const char *var_name, const char *value) +{ + char *t_name = 0, *t_val = 0; + + if (!usrmsg || !var_name || !value) { + return FTDM_FAIL; + } + + if (!usrmsg->variables) { + /* initialize on first use */ + usrmsg->variables = create_hashtable(16, ftdm_hash_hashfromstring, ftdm_hash_equalkeys); + ftdm_assert_return(usrmsg->variables, FTDM_FAIL, "Failed to create hash table\n"); + } + + t_name = ftdm_strdup(var_name); + t_val = ftdm_strdup(value); + hashtable_insert(usrmsg->variables, t_name, t_val, HASHTABLE_FLAG_FREE_KEY | HASHTABLE_FLAG_FREE_VALUE); + return FTDM_SUCCESS; +} + +FT_DECLARE(const char *) ftdm_usrmsg_get_var(ftdm_usrmsg_t *usrmsg, const char *var_name) +{ + const char *var = NULL; + + if (!usrmsg || !usrmsg->variables || !var_name) { + return NULL; + } + + var = (const char *)hashtable_search(((struct hashtable*)usrmsg->variables), (void *)var_name); + return var; +} diff --git a/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.c b/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.c index 818f1c5754..21008e6c96 100644 --- a/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.c +++ b/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.c @@ -182,7 +182,7 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_analog_configure_span) const char *tonemap = "us"; const char *hotline = ""; uint32_t digit_timeout = 10; - uint32_t wait_dialtone_timeout = 30000; + uint32_t wait_dialtone_timeout = 5000; uint32_t max_dialstr = MAX_DTMF; uint32_t polarity_delay = 600; const char *var, *val; @@ -226,7 +226,7 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_analog_configure_span) if (wait_dialtone_timeout < 0) { wait_dialtone_timeout = 0; } - ftdm_log_chan(span->channels[i], FTDM_LOG_DEBUG, "Wait dial tone ms = %d\n", wait_dialtone_timeout); + ftdm_log(FTDM_LOG_DEBUG, "Wait dial tone ms = %d\n", wait_dialtone_timeout); } else if (!strcasecmp(var, "enable_callerid")) { if (!(val = va_arg(ap, char *))) { break; diff --git a/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.c b/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.c index 5b4ce7196a..a7b84ea5d8 100644 --- a/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.c +++ b/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.c @@ -285,10 +285,7 @@ static FIO_SPAN_GET_SIG_STATUS_FUNCTION(isdn_get_span_sig_status) */ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(isdn_outgoing_call) { - ftdm_status_t status = FTDM_SUCCESS; - ftdm_set_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND); - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DIALING); - return status; + return FTDM_SUCCESS; } /** @@ -300,7 +297,14 @@ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(isdn_outgoing_call) #ifdef __TODO__ static FIO_CHANNEL_REQUEST_FUNCTION(isdn_channel_request) { +#if 1 /* FIXME caller_data.raw_data does not exist anymore, see docs/variables.txt for more info */ + Q931mes_Generic empty_gen; + Q931mes_Generic *gen = &empty_gen; + + memset(&empty_gen, 0, sizeof(empty_gen)) ; +#else Q931mes_Generic *gen = (Q931mes_Generic *) caller_data->raw_data; +#endif Q931ie_BearerCap BearerCap; Q931ie_ChanID ChanID = { 0 }; Q931ie_CallingNum CallingNum; @@ -1095,12 +1099,16 @@ static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic #ifdef __TODO_OR_REMOVE__ ftdmchan->caller_data.CRV = gen->CRV; #endif +#if 0 /* FIXME */ if (cplen > sizeof(caller_data->raw_data)) { cplen = sizeof(caller_data->raw_data); } +#endif gen->CRVFlag = !(gen->CRVFlag); +#if 0 /* FIXME */ memcpy(caller_data->raw_data, msg, cplen); caller_data->raw_data_len = cplen; +#endif fail = 0; } } @@ -1298,12 +1306,20 @@ static int ftdm_isdn_921_21(void *pvt, L2UCHAR *msg, L2INT mlen) static __inline__ void state_advance(ftdm_channel_t *ftdmchan) { - Q931mes_Generic *gen = (Q931mes_Generic *) ftdmchan->caller_data.raw_data; ftdm_isdn_data_t *isdn_data = ftdmchan->span->signal_data; ftdm_span_t *span = ftdm_channel_get_span(ftdmchan); ftdm_sigmsg_t sig; ftdm_status_t status; +#if 1 /* FIXME caller_data.raw_data does not exist anymore, see docs/variables.txt for more info */ + Q931mes_Generic empty_gen; + Q931mes_Generic *gen = &empty_gen; + + memset(&empty_gen, 0, sizeof(empty_gen)) ; +#else + Q931mes_Generic *gen = (Q931mes_Generic *) ftdmchan->caller_data.raw_data; +#endif + ftdm_log(FTDM_LOG_DEBUG, "%d:%d STATE [%s]\n", ftdm_channel_get_span_id(ftdmchan), ftdm_channel_get_id(ftdmchan), @@ -1431,7 +1447,9 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) gen->MesType = Q931mes_CONNECT; gen->BearerCap = 0; gen->CRVFlag = 1; /* inbound call */ +#if 0 /* FIXME */ Q931Rx43(&isdn_data->q931, gen, ftdmchan->caller_data.raw_data_len); +#endif } } break; diff --git a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c index 2f9c70a48d..e051477346 100644 --- a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c +++ b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c @@ -93,10 +93,7 @@ static FIO_SPAN_GET_SIG_STATUS_FUNCTION(isdn_get_span_sig_status) */ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(isdn_outgoing_call) { - ftdm_status_t status = FTDM_SUCCESS; - ftdm_set_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND); - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DIALING); - return status; + return FTDM_SUCCESS; } /** diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.2008.vcproj b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.2008.vcproj index 8942a8f5b6..565a31e505 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.2008.vcproj +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.2008.vcproj @@ -185,6 +185,10 @@ RelativePath=".\ftmod_r2.c" > + + diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c old mode 100644 new mode 100755 index 540d7cb6e9..c47f97a50b --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -47,8 +47,10 @@ #endif #include #include -#include "freetdm.h" -#include "private/ftdm_core.h" +#include +#include + +#include "ftmod_r2_io_mf_lib.h" // ftdm_r2_get_native_channel_mf_generation_iface /* when the user stops a span, we clear FTDM_R2_SPAN_STARTED, so that the signaling thread * knows it must stop, and we wait for FTDM_R2_RUNNING to be clear, which tells us the @@ -105,6 +107,7 @@ typedef struct ft_r2_conf_s { int charge_calls; int forced_release; int allow_collect_calls; + int use_channel_native_mf_generation; } ft_r2_conf_t; /* r2 configuration stored in span->signal_data */ @@ -286,9 +289,6 @@ static ftdm_call_cause_t ftdm_r2_cause_to_ftdm_cause(ftdm_channel_t *fchan, open case OR2_CAUSE_UNSPECIFIED: return FTDM_CAUSE_NORMAL_UNSPECIFIED; - case OR2_CAUSE_COLLECT_CALL_REJECTED: - return FTDM_CAUSE_CALL_REJECTED; - case OR2_CAUSE_FORCED_RELEASE: return FTDM_CAUSE_NORMAL_CLEARING; @@ -307,6 +307,7 @@ static openr2_call_disconnect_cause_t ftdm_r2_ftdm_cause_to_openr2_cause(ftdm_ch return OR2_CAUSE_NORMAL_CLEARING; case FTDM_CAUSE_USER_BUSY: + case FTDM_CAUSE_CALL_REJECTED: return OR2_CAUSE_BUSY_NUMBER; case FTDM_CAUSE_SWITCH_CONGESTION: @@ -334,7 +335,7 @@ static openr2_call_disconnect_cause_t ftdm_r2_ftdm_cause_to_openr2_cause(ftdm_ch return OR2_CAUSE_GLARE; } - ftdm_log_chan(fchan, FTDM_LOG_WARNING, "freetdm hangup cause %d mapped to openr2 cause %s\n", + ftdm_log_chan(fchan, FTDM_LOG_NOTICE, "freetdm hangup cause %d mapped to openr2 cause %s\n", fchan->caller_data.hangup_cause, openr2_proto_get_disconnect_string(OR2_CAUSE_UNSPECIFIED)); return OR2_CAUSE_UNSPECIFIED; } @@ -471,12 +472,9 @@ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(r2_outgoing_call) return FTDM_FAIL; } - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DIALING); - ftdm_channel_set_feature(ftdmchan, FTDM_CHANNEL_FEATURE_IO_STATS); ftdm_channel_command(ftdmchan, FTDM_COMMAND_FLUSH_TX_BUFFERS, NULL); ftdm_channel_command(ftdmchan, FTDM_COMMAND_FLUSH_RX_BUFFERS, NULL); - return FTDM_SUCCESS; } @@ -673,13 +671,13 @@ static void ftdm_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, cons ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan); ftdm_r2_data_t *r2data = ftdmchan->span->signal_data; - ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Call offered with ANI = %s, DNIS = %s, Category = %d, ANI restricted = %s\n", - ani, dnis, category, ani_restricted ? "Yes" : "No"); + ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Call offered with ANI = %s, DNIS = %s, Category = %s, ANI restricted = %s\n", + ani, dnis, openr2_proto_get_category_string(category), ani_restricted ? "Yes" : "No"); /* check if this is a collect call and if we should accept it */ if (!r2data->allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) { ftdm_log_chan_msg(ftdmchan, FTDM_LOG_NOTICE, "Rejecting collect call\n"); - openr2_chan_disconnect_call(r2chan, OR2_CAUSE_COLLECT_CALL_REJECTED); + openr2_chan_disconnect_call(r2chan, OR2_CAUSE_UNALLOCATED_NUMBER); } else { ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING); } @@ -1447,7 +1445,8 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_r2_configure_span_signaling) /* .double_answer */ -1, /* .charge_calls */ -1, /* .forced_release */ -1, - /* .allow_collect_calls */ -1 + /* .allow_collect_calls */ -1, + /* .use_channel_native_mf_generation */ 0 }; ftdm_assert_return(sig_cb != NULL, FTDM_FAIL, "No signaling cb provided\n"); @@ -1566,6 +1565,9 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_r2_configure_span_signaling) } else if (!strcasecmp(var, "max_dnis")) { r2conf.max_dnis = atoi(val); ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with max dnis = %d\n", span->name, r2conf.max_dnis); + } else if (!strcasecmp(var, "use_channel_native_mf_generation")) { + r2conf.use_channel_native_mf_generation = ftdm_true(val); + ftdm_log(FTDM_LOG_DEBUG, "Configuring R2 span %s with \"use native channel MF generation\" = %d\n", span->name, r2conf.use_channel_native_mf_generation); } else { snprintf(span->last_error, sizeof(span->last_error), "Unknown R2 parameter [%s]", var); return FTDM_FAIL; @@ -1617,6 +1619,10 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_r2_configure_span_signaling) openr2_context_configure_from_advanced_file(r2data->r2context, r2conf.advanced_protocol_file); } + if(r2conf.use_channel_native_mf_generation) { + openr2_context_set_mflib_interface(r2data->r2context, ftdm_r2_get_native_channel_mf_generation_iface()); + } + spanpvt->r2calls = create_hashtable(FTDM_MAX_CHANNELS_SPAN, ftdm_hash_hashfromstring, ftdm_hash_equalkeys); if (!spanpvt->r2calls) { snprintf(span->last_error, sizeof(span->last_error), "Cannot create channel calls hash for span."); @@ -1634,13 +1640,29 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_r2_configure_span_signaling) openr2_chan_enable_call_files(r2chan); } - r2call = ftdm_malloc(sizeof(*r2call)); + if (r2conf.use_channel_native_mf_generation) { + /* Allocate a new write handle per r2chan */ + ftdm_r2_mf_write_handle_t *mf_write_handle = ftdm_calloc(1, sizeof(*mf_write_handle)); + /* Associate to the FreeTDM channel */ + mf_write_handle->ftdmchan = span->channels[i]; + /* Make sure the FreeTDM channel supports MF the generation feature */ + if (!ftdm_channel_test_feature(mf_write_handle->ftdmchan, FTDM_CHANNEL_FEATURE_MF_GENERATE)) { + ftdm_log_chan_msg(mf_write_handle->ftdmchan, FTDM_LOG_ERROR, + "FreeTDM channel does not support native MF generation: " + "\"use_channel_native_mf_generation\" configuration parameter cannot" + " be used\n"); + goto fail; + } + /* Associate the mf_write_handle to the openR2 channel */ + openr2_chan_set_mflib_handles(r2chan, mf_write_handle, NULL); + } + + r2call = ftdm_calloc(1, sizeof(*r2call)); if (!r2call) { snprintf(span->last_error, sizeof(span->last_error), "Cannot create all R2 call data structures for the span."); ftdm_safe_free(r2chan); goto fail; } - memset(r2call, 0, sizeof(*r2call)); openr2_chan_set_logging_func(r2chan, ftdm_r2_on_chan_log); openr2_chan_set_client_data(r2chan, span->channels[i]); r2call->r2chan = r2chan; @@ -1651,6 +1673,7 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_r2_configure_span_signaling) } r2data->mf_dump_size = r2conf.mf_dump_size; r2data->category = r2conf.category; + r2data->allow_collect_calls = r2conf.allow_collect_calls; r2data->flags = 0; spanpvt->r2context = r2data->r2context; @@ -2370,5 +2393,5 @@ EX_DECLARE_DATA ftdm_module_t ftdm_module = { * c-basic-offset:4 * End: * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 + * vim:set softtabstop=4 shiftwidth=4 tabstop=4: */ diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2_io_mf_lib.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2_io_mf_lib.c new file mode 100755 index 0000000000..961da2cede --- /dev/null +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2_io_mf_lib.c @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2011 Sebastien Trottier + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of the original author; nor the names of any contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include + +#include + +#include "ftmod_r2_io_mf_lib.h" + +/* Convert openr2 MF tone enum value to FreeTDM MF tone value + 1-15 bitwise OR FTDM_MF_DIRECTION_FORWARD/BACKWARD + 0 (stop playing) + openr2_mf_tone_t defined in r2proto.h +*/ +static int ftdm_r2_openr2_mf_tone_to_ftdm_mf_tone(openr2_mf_tone_t + openr2_tone_value, int forward_signals) +{ + int tone; + + switch (openr2_tone_value) { + case 0: return 0; +#define TONE_FROM_NAME(name) case OR2_MF_TONE_##name: tone = name; break; + TONE_FROM_NAME(1) + TONE_FROM_NAME(2) + TONE_FROM_NAME(3) + TONE_FROM_NAME(4) + TONE_FROM_NAME(5) + TONE_FROM_NAME(6) + TONE_FROM_NAME(7) + TONE_FROM_NAME(8) + TONE_FROM_NAME(9) + TONE_FROM_NAME(10) + TONE_FROM_NAME(11) + TONE_FROM_NAME(12) + TONE_FROM_NAME(13) + TONE_FROM_NAME(14) + TONE_FROM_NAME(15) +#undef TONE_FROM_NAME + default: + ftdm_assert(0, "Invalid openr2_tone_value\n"); + return -1; + } + + /* Add flag corresponding to direction */ + if (forward_signals) { + tone |= FTDM_MF_DIRECTION_FORWARD; + } else { + tone |= FTDM_MF_DIRECTION_BACKWARD; + } + + return tone; +} + +/* MF generation routines (using IO command of a FreeTDM channel) + write_init stores the direction of the MF to generate */ +static void *ftdm_r2_io_mf_write_init(ftdm_r2_mf_write_handle_t *handle, int forward_signals) +{ + ftdm_log_chan(handle->ftdmchan, FTDM_LOG_DEBUG, "ftdm_r2_io_mf_write_init, " + "forward = %d\n", forward_signals); + + handle->fwd = forward_signals; + return handle; +} + +static int ftdm_r2_io_mf_generate_tone(ftdm_r2_mf_write_handle_t *handle, int16_t buffer[], int samples) +{ + /* Our mf_want_generate implementation always return 0, so mf_generate_tone should never be called */ + ftdm_assert(0, "ftdm_r2_io_mf_generate_tone not implemented\n"); + return 0; +} + +/* \brief mf_select_tone starts tone generation or stops current tone + * \return 0 on success, -1 on error + */ +static int ftdm_r2_io_mf_select_tone(ftdm_r2_mf_write_handle_t *handle, char signal) +{ + int tone; /* (0, 1-15) (0 meaning to stop playing) */ + + ftdm_log_chan(handle->ftdmchan, FTDM_LOG_DEBUG, "ftdm_r2_io_mf_select_tone, " + "signal = %c\n", signal); + + if (-1 == (tone = ftdm_r2_openr2_mf_tone_to_ftdm_mf_tone(signal, handle->fwd))) { + return -1; + } + + /* Start/stop playback directly here, as select tone is called each time a tone + is started or stopped (called if tone changes, but silence is tone 0, + triggering a tone change) */ + if (tone > 0) { + ftdm_channel_command(handle->ftdmchan, FTDM_COMMAND_START_MF_PLAYBACK, &tone); + } else { + /* tone 0 means to stop current tone */ + ftdm_channel_command(handle->ftdmchan, FTDM_COMMAND_STOP_MF_PLAYBACK, NULL); + } + return 0; +} + +static int ftdm_r2_io_mf_want_generate(ftdm_r2_mf_write_handle_t *handle, int signal) +{ + /* Return 0, meaning mf_generate_tone doesn't need to be called */ + return 0; +} + +/* MF lib interface that generate MF tones via FreeTDM channel IO commands + MF detection using the default openr2 provider (r2engine) */ +static openr2_mflib_interface_t g_mf_ftdm_io_iface = { + /* .mf_read_init */ (openr2_mf_read_init_func)openr2_mf_rx_init, + /* .mf_write_init */ (openr2_mf_write_init_func)ftdm_r2_io_mf_write_init, + /* .mf_detect_tone */ (openr2_mf_detect_tone_func)openr2_mf_rx, + /* .mf_generate_tone */ (openr2_mf_generate_tone_func)ftdm_r2_io_mf_generate_tone, + /* .mf_select_tone */ (openr2_mf_select_tone_func)ftdm_r2_io_mf_select_tone, + /* .mf_want_generate */ (openr2_mf_want_generate_func)ftdm_r2_io_mf_want_generate, + /* .mf_read_dispose */ NULL, + /* .mf_write_dispose */ NULL +}; + +openr2_mflib_interface_t *ftdm_r2_get_native_channel_mf_generation_iface() +{ + return &g_mf_ftdm_io_iface; +} + +/* For Emacs: + * Local Variables: + * mode:c + * indent-tabs-mode:t + * tab-width:4 + * c-basic-offset:4 + * End: + * For VIM: + * vim:set softtabstop=4 shiftwidth=4 tabstop=4 + */ diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2_io_mf_lib.h b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2_io_mf_lib.h new file mode 100755 index 0000000000..10fe3f3aab --- /dev/null +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2_io_mf_lib.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2011 Sebastien Trottier + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of the original author; nor the names of any contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _FTMOD_R2_IO_MFLIB_H_ +#define _FTMOD_R2_IO_MFLIB_H_ + +#include + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +/* MFC/R2 tone generator handle (mf_write_handle) */ +typedef struct { + /*! FTDM channel performing the MF generation */ + ftdm_channel_t *ftdmchan; + /*! 1 if generating forward tones, otherwise generating reverse tones. */ + int fwd; +} ftdm_r2_mf_write_handle_t; + +/* MF lib interface that generate MF tones via FreeTDM channel IO commands + MF detection using the default openr2 provider (r2engine) */ +openr2_mflib_interface_t *ftdm_r2_get_native_channel_mf_generation_iface(void); + +#if defined(__cplusplus) +} /* endif extern "C" */ +#endif + +#endif /* endif defined _FTMOD_R2_IO_MFLIB_H_ */ + +/* For Emacs: + * Local Variables: + * mode:c + * indent-tabs-mode:t + * tab-width:4 + * c-basic-offset:4 + * End: + * For VIM: + * vim:set softtabstop=4 shiftwidth=4 tabstop=4: + */ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c index 608b0b6ac0..d119ff4fd2 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c @@ -603,6 +603,7 @@ static ftdm_status_t ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdm ftdm_sigmsg_t sigev; ftdm_channel_state_t initial_state; sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data; + uint8_t state_change = 0; memset(&sigev, 0, sizeof(sigev)); @@ -610,9 +611,6 @@ static ftdm_status_t ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdm sigev.span_id = ftdmchan->span_id; sigev.channel = ftdmchan; - /* Acknowledge the state change */ - ftdm_channel_complete_state(ftdmchan); - #ifdef FTDM_DEBUG_CHAN_MEMORY if (ftdmchan->state == FTDM_CHANNEL_STATE_DIALING) { ftdm_assert(mprotect(ftdmchan, sizeof(*ftdmchan), PROT_READ) == 0, "Failed to mprotect"); @@ -649,8 +647,7 @@ static ftdm_status_t ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdm ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending incoming call from %s to %s to FTDM core\n", ftdmchan->caller_data.ani.digits, ftdmchan->caller_data.dnis.digits); /* we have enough information to inform FTDM of the call*/ - sigev.event_id = FTDM_SIGEVENT_START; - ftdm_span_send_signal(ftdmchan->span, &sigev); + sngisdn_send_signal(sngisdn_info, FTDM_SIGEVENT_START); } break; case FTDM_CHANNEL_STATE_DIALING: /* outgoing call request */ @@ -674,9 +671,10 @@ static ftdm_status_t ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdm { if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { /*OUTBOUND...so we were told by the line of this so noifiy the user*/ - sigev.event_id = FTDM_SIGEVENT_PROCEED; - ftdm_span_send_signal(ftdmchan->span, &sigev); + sngisdn_send_signal(sngisdn_info, FTDM_SIGEVENT_PROCEED); + if (sngisdn_test_flag(sngisdn_info, FLAG_MEDIA_READY)) { + state_change++; ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA); } } else { @@ -694,9 +692,10 @@ static ftdm_status_t ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdm { if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { /* OUTBOUND...so we were told by the line of this so notify the user */ - sigev.event_id = FTDM_SIGEVENT_RINGING; - ftdm_span_send_signal(ftdmchan->span, &sigev); + sngisdn_send_signal(sngisdn_info, FTDM_SIGEVENT_RINGING); + if (sngisdn_test_flag(sngisdn_info, FLAG_MEDIA_READY)) { + state_change++; ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA); } } else { @@ -710,8 +709,8 @@ static ftdm_status_t ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdm /*check if the channel is inbound or outbound*/ if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { /*OUTBOUND...so we were told by the line of this so noifiy the user*/ - sigev.event_id = FTDM_SIGEVENT_PROGRESS; - ftdm_span_send_signal(ftdmchan->span, &sigev); + + sngisdn_send_signal(sngisdn_info, FTDM_SIGEVENT_PROGRESS); } else { /* Send a progress message, indicating: Call is not end-to-end ISDN, further call progress may be available */ ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_NETE_ISDN}; @@ -722,8 +721,7 @@ static ftdm_status_t ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdm case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: { if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { - sigev.event_id = FTDM_SIGEVENT_PROGRESS_MEDIA; - ftdm_span_send_signal(ftdmchan->span, &sigev); + sngisdn_send_signal(sngisdn_info, FTDM_SIGEVENT_PROGRESS_MEDIA); } else { /* Send a progress message, indicating: In-band information/pattern available */ ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_IB_AVAIL}; @@ -736,8 +734,8 @@ static ftdm_status_t ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdm /* check if the channel is inbound or outbound */ if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { /* OUTBOUND ... so we were told by the line that the other side answered */ - sigev.event_id = FTDM_SIGEVENT_UP; - ftdm_span_send_signal(ftdmchan->span, &sigev); + + sngisdn_send_signal(sngisdn_info, FTDM_SIGEVENT_UP); if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP && ((sngisdn_span_data_t*)ftdmchan->span->signal_data)->signalling == SNGISDN_SIGNALING_NET) { @@ -757,14 +755,14 @@ static ftdm_status_t ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdm /* Send a release complete */ sngisdn_snd_release(ftdmchan, 0); /*now go to the HANGUP complete state*/ + state_change++; ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE); } break; case FTDM_CHANNEL_STATE_TERMINATING: /* call is hung up by the remote end */ { /* this state is set when the line is hanging up */ - sigev.event_id = FTDM_SIGEVENT_STOP; - ftdm_span_send_signal(ftdmchan->span, &sigev); + sngisdn_send_signal(sngisdn_info, FTDM_SIGEVENT_STOP); } break; case FTDM_CHANNEL_STATE_HANGUP: /* call is hung up locally */ @@ -817,6 +815,7 @@ static ftdm_status_t ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdm } } /* now go to the HANGUP complete state */ + state_change++; ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE); } break; @@ -825,6 +824,7 @@ static ftdm_status_t ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdm if (sngisdn_test_flag(sngisdn_info, FLAG_REMOTE_ABORT) || sngisdn_test_flag(sngisdn_info, FLAG_LOCAL_ABORT)) { /* If the remote side aborted, we will not get anymore message for this call */ + state_change++; ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); } else { /* waiting on remote confirmation before moving to down */ @@ -878,7 +878,27 @@ static ftdm_status_t ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdm } break; } + + if (!state_change) { + /* Acknowledge the state change */ + ftdm_channel_complete_state(ftdmchan); + } + /* If sngisdn_info->variables is not NULL, it means did not send any + * sigevent to the user, therefore we have to free that hashtable */ + if (sngisdn_info->variables) { + hashtable_destroy(sngisdn_info->variables); + sngisdn_info->variables = NULL; + } + + /* If sngisdn_info->raw_data is not NULL, it means did not send any + * sigevent to the user, therefore we have to free that raw data */ + if (sngisdn_info->raw_data) { + ftdm_safe_free(sngisdn_info->raw_data); + sngisdn_info->raw_data = NULL; + sngisdn_info->raw_data_len = 0; + } + if (ftdmchan->state == initial_state) { ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "state change flag is still set, but we did not change state\n"); } @@ -890,20 +910,18 @@ static ftdm_status_t ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdm return FTDM_SUCCESS; } -static FIO_CHANNEL_SEND_MSG_FUNCTION(ftdm_sangoma_isdn_send_msg) +static FIO_CHANNEL_INDICATE_FUNCTION(ftdm_sangoma_isdn_indicate) { ftdm_status_t status = FTDM_FAIL; - switch (sigmsg->event_id) { - case FTDM_SIGEVENT_FACILITY: + switch (indication) { + case FTDM_CHANNEL_INDICATE_FACILITY: sngisdn_snd_fac_req(ftdmchan); status = FTDM_SUCCESS; break; default: - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Unsupported signalling msg requested\n"); - status = FTDM_BREAK; - } - ftdm_call_clear_data(&ftdmchan->caller_data); + status = FTDM_NOTIMPL; + } return status; } @@ -911,34 +929,25 @@ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(ftdm_sangoma_isdn_outgoing_call) { sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data; ftdm_status_t status = FTDM_FAIL; - - switch (ftdmchan->state) { - case FTDM_CHANNEL_STATE_DOWN: - { - if (sngisdn_test_flag(sngisdn_info, FLAG_GLARE)) { - /* A call came in after we called ftdm_channel_open_chan for this call, but before we got here */ - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Glare detected - aborting outgoing call\n"); + if (ftdmchan->state == FTDM_CHANNEL_STATE_DOWN) { + if (sngisdn_test_flag(sngisdn_info, FLAG_GLARE)) { + /* A call came in after we called ftdm_channel_open_chan for this call, but before we got here */ + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Glare detected - aborting outgoing call\n"); - sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT); - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE); + sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE); - status = FTDM_BREAK; - } else { - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DIALING); - status = FTDM_SUCCESS; - } - } - break; - default: - { - /* the channel is already used...this can't be, end the request */ - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Outgoing call requested channel in already in use\n"); status = FTDM_BREAK; + } else { + status = FTDM_SUCCESS; } - break; + } else { + /* the channel is already used...this can't be, end the request */ + ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Outgoing call requested channel in already in use (%s)\n", ftdm_channel_state2str(ftdmchan->state)); + status = FTDM_BREAK; } - + return status; } static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(ftdm_sangoma_isdn_get_chan_sig_status) @@ -1090,7 +1099,7 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_isdn_span_config) span->stop = ftdm_sangoma_isdn_stop; span->signal_type = FTDM_SIGTYPE_ISDN; span->outgoing_call = ftdm_sangoma_isdn_outgoing_call; - span->send_msg = ftdm_sangoma_isdn_send_msg; + span->indicate = ftdm_sangoma_isdn_indicate; span->channel_request = NULL; span->signal_cb = sig_cb; span->get_channel_sig_status = ftdm_sangoma_isdn_get_chan_sig_status; diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h index b369deae1f..43d6ad555e 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h @@ -181,6 +181,15 @@ typedef struct sngisdn_chan_data { uint8_t globalFlg; sngisdn_glare_data_t glare; ftdm_timer_id_t timers[SNGISDN_NUM_TIMERS]; + + /* variables saved here will be sent to the user application + on next SIGEVENT_XXX */ + ftdm_hash_t* variables; + + /* raw_data saved here will be sent to the user application + on next SIGEVENT_XXX */ + void *raw_data; + ftdm_size_t raw_data_len; } sngisdn_chan_data_t; /* Span specific data */ @@ -416,6 +425,12 @@ ftdm_status_t set_restart_ind_ie(ftdm_channel_t *ftdmchan, RstInd *rstInd); ftdm_status_t set_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr); ftdm_status_t set_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, uint8_t *data_len); + +ftdm_status_t sngisdn_add_var(sngisdn_chan_data_t *sngisdn_info, const char* var, const char* val); +ftdm_status_t sngisdn_add_raw_data(sngisdn_chan_data_t *sngisdn_info, uint8_t* data, ftdm_size_t data_len); +ftdm_status_t sngisdn_clear_data(sngisdn_chan_data_t *sngisdn_info); +void sngisdn_send_signal(sngisdn_chan_data_t *sngisdn_info, ftdm_signal_event_t event_id); + uint8_t sngisdn_get_infoTranCap_from_user(ftdm_bearer_cap_t bearer_capability); uint8_t sngisdn_get_usrInfoLyr1Prot_from_user(ftdm_user_layer1_prot_t layer1_prot); ftdm_bearer_cap_t sngisdn_get_infoTranCap_from_stack(uint8_t bearer_capability); diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c index bcc7d938b7..a9d2d06c32 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c @@ -160,8 +160,12 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event) } } - /* this should be in get_facility_ie function, fix this later */ - if (signal_data->facility == SNGISDN_OPT_TRUE && conEvnt->facilityStr.eh.pres) { +#if 1 + /* this section will not be needed once asn decoding function with key-value pairs is implemented */ + if (signal_data->facility == SNGISDN_OPT_TRUE && + signal_data->facility_ie_decode != SNGISDN_OPT_FALSE && + conEvnt->facilityStr.eh.pres) { + /* Verify whether the Caller Name will come in a subsequent FACILITY message */ uint16_t ret_val; char retrieved_str[255]; @@ -187,6 +191,7 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event) strcpy(ftdmchan->caller_data.cid_name, retrieved_str); } } +#endif if (signal_data->overlap_dial == SNGISDN_OPT_TRUE && !conEvnt->sndCmplt.eh.pres) { ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_COLLECT); @@ -644,7 +649,7 @@ void sngisdn_process_rel_ind (sngisdn_event_data_t *sngisdn_event) break; case FTDM_CHANNEL_STATE_TERMINATING: if (sngisdn_test_flag(sngisdn_info, FLAG_GLARE) && - sngisdn_info->glare.suInstId != suInstId) { + sngisdn_info->glare.suInstId != suInstId) { /* This release if for the outbound call that we already started clearing */ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Received RELEASE for local glared call\n"); @@ -662,7 +667,6 @@ void sngisdn_process_rel_ind (sngisdn_event_data_t *sngisdn_event) default: ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Received RELEASE in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state)); - break; } @@ -830,7 +834,7 @@ void sngisdn_process_fac_ind (sngisdn_event_data_t *sngisdn_event) If there will be no information following, but current FACILITY IE contains a caller name, returns 0 If there will be information following, returns 1 */ - + if (sng_isdn_retrieve_facility_caller_name(&facEvnt->facElmt.facStr.val[2], facEvnt->facElmt.facStr.len, retrieved_str) == 0) { strcpy(ftdmchan->caller_data.cid_name, retrieved_str); } else { diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c index 4b27f21e1c..b56c95b10d 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c @@ -156,8 +156,6 @@ void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_i set_prog_ind_ie(ftdmchan, &cnStEvnt.progInd, prog_ind); set_facility_ie(ftdmchan, &cnStEvnt.facilityStr); - ftdm_call_clear_data(&ftdmchan->caller_data); - ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending PROCEED (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces); if(sng_isdn_con_status(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &cnStEvnt, MI_CALLPROC, signal_data->dchan_id, sngisdn_info->ces)) { @@ -189,7 +187,6 @@ void sngisdn_snd_progress(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ memset(&cnStEvnt, 0, sizeof(cnStEvnt)); set_prog_ind_ie(ftdmchan, &cnStEvnt.progInd, prog_ind); set_facility_ie(ftdmchan, &cnStEvnt.facilityStr); - ftdm_call_clear_data(&ftdmchan->caller_data); ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending PROGRESS (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces); if(sng_isdn_con_status(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId,&cnStEvnt, MI_PROGRESS, signal_data->dchan_id, sngisdn_info->ces)) { @@ -216,7 +213,6 @@ void sngisdn_snd_alert(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind set_prog_ind_ie(ftdmchan, &cnStEvnt.progInd, prog_ind); set_facility_ie(ftdmchan, &cnStEvnt.facilityStr); - ftdm_call_clear_data(&ftdmchan->caller_data); ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending ALERT (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces); @@ -241,11 +237,10 @@ void sngisdn_snd_connect(ftdm_channel_t *ftdmchan) } memset(&cnStEvnt, 0, sizeof(cnStEvnt)); - + set_chan_id_ie(ftdmchan, &cnStEvnt.chanId); set_prog_ind_ie(ftdmchan, &cnStEvnt.progInd, prog_ind); set_facility_ie(ftdmchan, &cnStEvnt.facilityStr); - ftdm_call_clear_data(&ftdmchan->caller_data); ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending CONNECT (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces); if (sng_isdn_con_response(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &cnStEvnt, signal_data->dchan_id, sngisdn_info->ces)) { @@ -272,14 +267,13 @@ void sngisdn_snd_fac_req(ftdm_channel_t *ftdmchan) /* No point in sending a FACILITY message if there is no Facility IE to transmit */ return; } - ftdm_call_clear_data(&ftdmchan->caller_data); facEvnt.facElmt.eh.pres = PRSNT_NODEF; facEvnt.facElmt.facStr.pres = PRSNT_NODEF; facEvnt.facElmt.facStr.val[0] = 0x1C; facEvnt.facElmt.facStr.val[1] = (uint8_t)facEvnt.facElmt.facStr.len; facEvnt.facElmt.facStr.len +=2; /* Need to include the size of identifier + len */ - + ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending FACILITY (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces); if (sng_isdn_facility_request(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &facEvnt, MI_FACIL, signal_data->dchan_id, sngisdn_info->ces)) { @@ -306,7 +300,7 @@ void sngisdn_snd_info_req(ftdm_channel_t *ftdmchan) //ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Sending INFO REQ\n"); - ftdm_call_clear_data(&ftdmchan->caller_data); + ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending INFO REQ (suId:%d dchan:%d ces:%d)\n", signal_data->cc_id, signal_data->dchan_id, sngisdn_info->ces); @@ -327,8 +321,6 @@ void sngisdn_snd_status_enq(ftdm_channel_t *ftdmchan) //ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Sending STATUS ENQ\n"); memset(&staEvnt, 0, sizeof(StaEvnt)); - - ftdm_call_clear_data(&ftdmchan->caller_data); ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending Status ENQ on suId:%d suInstId:%u spInstId:%d dchan:%d ces:%d\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces); if (sng_isdn_status_request(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &staEvnt, MI_STATENQ)) { @@ -367,8 +359,7 @@ void sngisdn_snd_disconnect(ftdm_channel_t *ftdmchan) discEvnt.causeDgn[0].recommend.pres = NOTPRSNT; discEvnt.causeDgn[0].dgnVal.pres = NOTPRSNT; - set_facility_ie(ftdmchan, &discEvnt.facilityStr); - ftdm_call_clear_data(&ftdmchan->caller_data); + set_facility_ie(ftdmchan, &discEvnt.facilityStr); ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending DISCONNECT (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId); if (sng_isdn_disc_request(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &discEvnt)) { @@ -416,7 +407,6 @@ void sngisdn_snd_release(ftdm_channel_t *ftdmchan, uint8_t glare) } set_facility_ie(ftdmchan, &relEvnt.facilityStr); - ftdm_call_clear_data(&ftdmchan->caller_data); ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending RELEASE/RELEASE COMPLETE (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, suInstId, spInstId); diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c index 08e5984a4f..d24f2d403d 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c @@ -225,26 +225,26 @@ ftdm_status_t get_calling_num2(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb) } if (cgPtyNmb->screenInd.pres == PRSNT_NODEF) { - ftdm_call_add_var(caller_data, "isdn.cg_pty2.screen_ind", ftdm_screening2str(cgPtyNmb->screenInd.val)); + sngisdn_add_var((sngisdn_chan_data_t*)ftdmchan->call_data, "isdn.cg_pty2.screen_ind", ftdm_screening2str(cgPtyNmb->screenInd.val)); } if (cgPtyNmb->presInd0.pres == PRSNT_NODEF) { - ftdm_call_add_var(caller_data, "isdn.cg_pty2.presentation_ind", ftdm_presentation2str(cgPtyNmb->presInd0.val)); + sngisdn_add_var((sngisdn_chan_data_t*)ftdmchan->call_data, "isdn.cg_pty2.presentation_ind", ftdm_presentation2str(cgPtyNmb->presInd0.val)); } if (cgPtyNmb->nmbPlanId.pres == PRSNT_NODEF) { - ftdm_call_add_var(caller_data, "isdn.cg_pty2.npi", ftdm_npi2str(cgPtyNmb->nmbPlanId.val)); + sngisdn_add_var((sngisdn_chan_data_t*)ftdmchan->call_data, "isdn.cg_pty2.npi", ftdm_npi2str(cgPtyNmb->nmbPlanId.val)); } if (cgPtyNmb->typeNmb1.pres == PRSNT_NODEF) { - ftdm_call_add_var(caller_data, "isdn.cg_pty2.ton", ftdm_ton2str(cgPtyNmb->typeNmb1.val)); + sngisdn_add_var((sngisdn_chan_data_t*)ftdmchan->call_data, "isdn.cg_pty2.ton", ftdm_ton2str(cgPtyNmb->typeNmb1.val)); } if (cgPtyNmb->nmbDigits.pres == PRSNT_NODEF) { char digits_string [32]; memcpy(digits_string, (const char*)cgPtyNmb->nmbDigits.val, cgPtyNmb->nmbDigits.len); digits_string[cgPtyNmb->nmbDigits.len] = '\0'; - ftdm_call_add_var(caller_data, "isdn.cg_pty2.digits", digits_string); + sngisdn_add_var((sngisdn_chan_data_t*)ftdmchan->call_data, "isdn.cg_pty2.digits", digits_string); } memcpy(&caller_data->ani, &caller_data->cid_num, sizeof(caller_data->ani)); return FTDM_SUCCESS; @@ -253,6 +253,7 @@ ftdm_status_t get_calling_num2(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb) ftdm_status_t get_called_num(ftdm_channel_t *ftdmchan, CdPtyNmb *cdPtyNmb) { ftdm_caller_data_t *caller_data = &ftdmchan->caller_data; + if (cdPtyNmb->eh.pres != PRSNT_NODEF) { return FTDM_FAIL; } @@ -343,7 +344,7 @@ ftdm_status_t get_calling_subaddr(ftdm_channel_t *ftdmchan, CgPtySad *cgPtySad) memcpy(subaddress, (char*)cgPtySad->sadInfo.val, cgPtySad->sadInfo.len); subaddress[cgPtySad->sadInfo.len] = '\0'; - ftdm_call_add_var(&ftdmchan->caller_data, "isdn.calling_subaddr", subaddress); + sngisdn_add_var((sngisdn_chan_data_t*)ftdmchan->call_data, "isdn.calling_subaddr", subaddress); return FTDM_SUCCESS; } @@ -358,21 +359,19 @@ ftdm_status_t get_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr ftdm_status_t get_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, uint8_t data_len) { - ftdm_caller_data_t *caller_data = &ftdmchan->caller_data; sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; if (signal_data->facility_ie_decode == SNGISDN_OPT_FALSE) { - /* size of facilityStr->facilityStr.len is a uint8_t so no need to check - for overflow here as facilityStr->facilityStr.len will always be smaller - than sizeof(caller_data->raw_data) */ + /* Max size of Facility IE is 255 */ + uint8_t my_data [255]; - memset(caller_data->raw_data, 0, sizeof(caller_data->raw_data)); /* Always include Facility IE identifier + len so this can be used as a sanity check by the user */ - caller_data->raw_data[0] = SNGISDN_Q931_FACILITY_IE_ID; - caller_data->raw_data[1] = data_len; - - memcpy(&caller_data->raw_data[2], data, data_len); - caller_data->raw_data_len = data_len+2; + my_data[0] = SNGISDN_Q931_FACILITY_IE_ID; + my_data[1] = data_len; + memcpy(&my_data[2], data, data_len); + + sngisdn_add_raw_data((sngisdn_chan_data_t*)ftdmchan->call_data, data, data_len+2); + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Raw Facility IE copied available\n"); } else { /* Call libsng_isdn to process facility IE's here */ @@ -382,7 +381,7 @@ ftdm_status_t get_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, uint8 ftdm_status_t get_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd) { - uint8_t val; + uint8_t val; if (!progInd->eh.pres) { return FTDM_FAIL; } @@ -412,7 +411,7 @@ ftdm_status_t get_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd) val = SNGISDN_PROGIND_DESCR_INVALID; break; } - ftdm_call_add_var(&ftdmchan->caller_data, "isdn.prog_ind.descr", ftdm_sngisdn_progind_descr2str(val)); + sngisdn_add_var((sngisdn_chan_data_t*)ftdmchan->call_data, "isdn.prog_ind.descr", ftdm_sngisdn_progind_descr2str(val)); } if (progInd->location.pres) { @@ -443,7 +442,7 @@ ftdm_status_t get_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd) val = SNGISDN_PROGIND_LOC_INVALID; break; } - ftdm_call_add_var(&ftdmchan->caller_data, "isdn.prog_ind.loc", ftdm_sngisdn_progind_loc2str(val)); + sngisdn_add_var((sngisdn_chan_data_t*)ftdmchan->call_data, "isdn.prog_ind.loc", ftdm_sngisdn_progind_loc2str(val)); } return FTDM_SUCCESS; } @@ -493,7 +492,7 @@ ftdm_status_t set_calling_num2(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb) uint8_t len,val; ftdm_caller_data_t *caller_data = &ftdmchan->caller_data; - string = ftdm_call_get_var(caller_data, "isdn.cg_pty2.digits"); + string = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "isdn.cg_pty2.digits"); if ((string == NULL) || !(*string)) { return FTDM_FAIL; } @@ -510,7 +509,7 @@ ftdm_status_t set_calling_num2(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb) cgPtyNmb->screenInd.pres = PRSNT_NODEF; val = FTDM_SCREENING_INVALID; - string = ftdm_call_get_var(caller_data, "isdn.cg_pty2.screening_ind"); + string = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "isdn.cg_pty2.screening_ind"); if ((string != NULL) && (*string)) { val = ftdm_str2ftdm_screening(string); } @@ -527,7 +526,7 @@ ftdm_status_t set_calling_num2(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb) cgPtyNmb->presInd0.pres = PRSNT_NODEF; val = FTDM_PRES_INVALID; - string = ftdm_call_get_var(caller_data, "isdn.cg_pty2.presentation_ind"); + string = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "isdn.cg_pty2.presentation_ind"); if ((string != NULL) && (*string)) { val = ftdm_str2ftdm_presentation(string); } @@ -542,7 +541,7 @@ ftdm_status_t set_calling_num2(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb) cgPtyNmb->nmbPlanId.pres = PRSNT_NODEF; val = FTDM_NPI_INVALID; - string = ftdm_call_get_var(caller_data, "isdn.cg_pty2.npi"); + string = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "isdn.cg_pty2.npi"); if ((string != NULL) && (*string)) { val = ftdm_str2ftdm_npi(string); } @@ -557,7 +556,7 @@ ftdm_status_t set_calling_num2(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb) /* Type of Number */ val = FTDM_TON_INVALID; - string = ftdm_call_get_var(caller_data, "isdn.cg_pty2.ton"); + string = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "isdn.cg_pty2.ton"); if ((string != NULL) && (*string)) { val = ftdm_str2ftdm_ton(string); } @@ -691,7 +690,7 @@ ftdm_status_t set_calling_name(ftdm_channel_t *ftdmchan, ConEvnt *conEvnt) ftdm_status_t set_calling_subaddr(ftdm_channel_t *ftdmchan, CgPtySad *cgPtySad) { const char* clg_subaddr = NULL; - clg_subaddr = ftdm_call_get_var(&ftdmchan->caller_data, "isdn.calling_subaddr"); + clg_subaddr = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "isdn.calling_subaddr"); if ((clg_subaddr != NULL) && (*clg_subaddr)) { unsigned len = strlen (clg_subaddr); cgPtySad->eh.pres = PRSNT_NODEF; @@ -721,14 +720,19 @@ ftdm_status_t set_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr ftdm_status_t set_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, uint8_t *data_len) { - int len; - ftdm_caller_data_t *caller_data = &ftdmchan->caller_data; - if (caller_data->raw_data_len > 0 && caller_data->raw_data[0] == SNGISDN_Q931_FACILITY_IE_ID) { - len = caller_data->raw_data[1]; - memcpy(data, &caller_data->raw_data[2], len); - *data_len = len; - return FTDM_SUCCESS; - } + ftdm_size_t len; + uint8_t *mydata; + void *vdata; + + if (ftdm_usrmsg_get_raw_data(ftdmchan->usrmsg, &vdata, &len) == FTDM_SUCCESS) { + mydata = vdata; + if (len > 2 && mydata[0] == SNGISDN_Q931_FACILITY_IE_ID) { + len = mydata[1]; + memcpy(data, &mydata[2], len); + *data_len = len; + return FTDM_SUCCESS; + } + } return FTDM_FAIL; } @@ -738,7 +742,7 @@ ftdm_status_t set_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd, ftdm_s int descr = prog_ind.descr; int loc = prog_ind.loc; - str = ftdm_call_get_var(&ftdmchan->caller_data, "isdn.prog_ind.descr"); + str = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "isdn.prog_ind.descr"); if (str && *str) { /* User wants to override progress indicator */ descr = ftdm_str2ftdm_sngisdn_progind_descr(str); @@ -749,7 +753,7 @@ ftdm_status_t set_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd, ftdm_s return FTDM_SUCCESS; } - str = ftdm_call_get_var(&ftdmchan->caller_data, "isdn.prog_ind.loc"); + str = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "isdn.prog_ind.loc"); if (str && *str) { loc = ftdm_str2ftdm_sngisdn_progind_loc(str); } @@ -869,7 +873,7 @@ ftdm_status_t set_chan_id_ie(ftdm_channel_t *ftdmchan, ChanId *chanId) ftdm_status_t set_bear_cap_ie(ftdm_channel_t *ftdmchan, BearCap *bearCap) { sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; - + bearCap->eh.pres = PRSNT_NODEF; bearCap->infoTranCap.pres = PRSNT_NODEF; bearCap->infoTranCap.val = sngisdn_get_infoTranCap_from_user(ftdmchan->caller_data.bearer_capability); @@ -1202,6 +1206,74 @@ void sngisdn_print_spans(ftdm_stream_handle_t *stream) return; } +ftdm_status_t sngisdn_add_var(sngisdn_chan_data_t *sngisdn_info, const char* var, const char* val) +{ + char *t_name = 0, *t_val = 0; + if (!var || !val) { + return FTDM_FAIL; + } + if (!sngisdn_info->variables) { + /* initialize on first use */ + sngisdn_info->variables = create_hashtable(16, ftdm_hash_hashfromstring, ftdm_hash_equalkeys); + ftdm_assert_return(sngisdn_info->variables, FTDM_FAIL, "Failed to create hash table\n"); + } + t_name = ftdm_strdup(var); + t_val = ftdm_strdup(val); + hashtable_insert(sngisdn_info->variables, t_name, t_val, HASHTABLE_FLAG_FREE_KEY | HASHTABLE_FLAG_FREE_VALUE); + return FTDM_SUCCESS; +} + +ftdm_status_t sngisdn_add_raw_data(sngisdn_chan_data_t *sngisdn_info, uint8_t* data, ftdm_size_t data_len) +{ + ftdm_assert_return(!sngisdn_info->raw_data, FTDM_FAIL, "Overwriting existing raw data\n"); + + sngisdn_info->raw_data = ftdm_calloc(1, data_len); + ftdm_assert_return(sngisdn_info->raw_data, FTDM_FAIL, "Failed to allocate raw data\n"); + + memcpy(sngisdn_info->raw_data, data, data_len); + sngisdn_info->raw_data_len = data_len; + return FTDM_SUCCESS; +} + +void sngisdn_send_signal(sngisdn_chan_data_t *sngisdn_info, ftdm_signal_event_t event_id) +{ + ftdm_sigmsg_t sigev; + ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan; + + memset(&sigev, 0, sizeof(sigev)); + + sigev.chan_id = ftdmchan->chan_id; + sigev.span_id = ftdmchan->span_id; + sigev.channel = ftdmchan; + sigev.event_id = event_id; + + if (sngisdn_info->variables) { + /* + * variables now belongs to the ftdm core, and + * will be cleared after sigev is processed by user. Set + * local pointer to NULL so we do not attempt to + * destroy it */ + sigev.variables = sngisdn_info->variables; + sngisdn_info->variables = NULL; + } + + if (sngisdn_info->raw_data) { + /* + * raw_data now belongs to the ftdm core, and + * will be cleared after sigev is processed by user. Set + * local pointer to NULL so we do not attempt to + * destroy it */ + + sigev.raw.data = sngisdn_info->raw_data; + sigev.raw.len = sngisdn_info->raw_data_len; + + sngisdn_info->raw_data = NULL; + sngisdn_info->raw_data_len = 0; + } + ftdm_span_send_signal(ftdmchan->span, &sigev); +} + + /* For Emacs: * Local Variables: * mode:c diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.c index a0a7cc681a..c2e9b5c3a1 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.c @@ -139,7 +139,6 @@ void sngisdn_trace_raw_q921(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t d memcpy(raw_data, data, data_len); sigev.raw.data = raw_data; sigev.raw.len = data_len; - sigev.raw.autofree = 1; ftdm_span_send_signal(signal_data->ftdm_span, &sigev); } @@ -258,7 +257,6 @@ void sngisdn_trace_raw_q931(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t d memcpy(raw_data, data, data_len); sigev.raw.data = raw_data; sigev.raw.len = data_len; - sigev.raw.autofree = 1; ftdm_span_send_signal(signal_data->ftdm_span, &sigev); } } @@ -841,7 +839,7 @@ static ftdm_status_t sngisdn_get_frame_info(uint8_t *data, uint32_t data_len, ft uint32_t tmp_len = 0; char tmp[1000]; print_hex_dump(tmp, &tmp_len, data, 0, data_len); - ftdm_log(FTDM_LOG_WARNING, "Failed to determine b-channel on SETUP message\n%s\n", tmp); + ftdm_log(FTDM_LOG_DEBUG, "Failed to determine b-channel on SETUP message\n%s\n", tmp); } } diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cfg.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cfg.c index df0414a7f5..b7eaa37639 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cfg.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cfg.c @@ -396,16 +396,13 @@ int ft_to_sngss7_cfg_all(void) x = (g_ftdm_sngss7_data.cfg.procId * 1000) + 1; while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) { - if ( g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) { - if (ftmod_ss7_isup_ckt_config(x)) { - SS7_CRITICAL("ISUP CKT %d configuration FAILED!\n", x); - return 1; - } else { - SS7_INFO("ISUP CKT %d configuration DONE!\n", x); - } - - } /* if ( g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) */ + if (ftmod_ss7_isup_ckt_config(x)) { + SS7_CRITICAL("ISUP CKT %d configuration FAILED!\n", x); + return 1; + } else { + SS7_INFO("ISUP CKT %d configuration DONE!\n", x); + } /* set the SNGSS7_CONFIGURED flag */ g_ftdm_sngss7_data.cfg.isupCkt[x].flags |= SNGSS7_CONFIGURED; diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c index 280107acd0..f8b12ea588 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c @@ -83,8 +83,8 @@ static ftdm_status_t handle_tx_lpr(ftdm_stream_handle_t *stream, char *name); static ftdm_status_t handle_status_mtp3link(ftdm_stream_handle_t *stream, char *name); static ftdm_status_t handle_status_mtp2link(ftdm_stream_handle_t *stream, char *name); static ftdm_status_t handle_status_linkset(ftdm_stream_handle_t *stream, char *name); - static ftdm_status_t handle_status_relay(ftdm_stream_handle_t *stream, char *name); +static ftdm_status_t handle_status_isup_ckt(ftdm_stream_handle_t *stream, char *id_name); static ftdm_status_t extract_span_chan(char *argv[10], int pos, int *span, int *chan); static ftdm_status_t check_arg_count(int args, int min); @@ -149,6 +149,25 @@ ftdm_status_t ftdm_sngss7_handle_cli_cmd(ftdm_stream_handle_t *stream, const cha handle_show_status(stream, span, chan, verbose); /******************************************************************/ + } else if (!strcasecmp(argv[c], "isup")) { + /******************************************************************/ + if (check_arg_count(argc, 4)) goto handle_cli_error_argc; + c++; + + if (!strcasecmp(argv[c], "ckt")) { + /**************************************************************/ + if (check_arg_count(argc, 5)) goto handle_cli_error_argc; + c++; + + handle_status_isup_ckt(stream, argv[c]); + /**************************************************************/ + } else { + /**************************************************************/ + stream->write_function(stream, "Unknown \"status isup\" command\n"); + goto handle_cli_error; + /**************************************************************/ + } + /******************************************************************/ } else { /******************************************************************/ stream->write_function(stream, "Unknown \"status\" command\n"); @@ -948,12 +967,14 @@ static ftdm_status_t handle_show_inreset(ftdm_stream_handle_t *stream, int span, /******************************************************************************/ static ftdm_status_t handle_show_flags(ftdm_stream_handle_t *stream, int span, int chan, int verbose) { - int x; - int bit; - sngss7_chan_data_t *ss7_info; - ftdm_channel_t *ftdmchan; - int lspan; - int lchan; + sngss7_chan_data_t *ss7_info; + ftdm_channel_t *ftdmchan; + int x; + int bit; + int lspan; + int lchan; + const char *text; + int flag; x = (g_ftdm_sngss7_data.cfg.procId * 1000) + 1; while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) { @@ -982,11 +1003,11 @@ static ftdm_status_t handle_show_flags(ftdm_stream_handle_t *stream, int span, i ss7_info->circuit->cic); for (bit = 0; bit < 33; bit++) { - stream->write_function(stream, "|"); if (ss7_info->ckt_flags & ( 0x1 << bit)) { - stream->write_function(stream, "%2d=1", bit); - } else { - stream->write_function(stream, "%2d=0", bit); + stream->write_function(stream, "|"); + flag = bit; + text = ftmod_ss7_ckt_flag2str(flag); + stream->write_function(stream, "%s",text); } } @@ -1037,37 +1058,37 @@ static ftdm_status_t handle_show_blocks(ftdm_stream_handle_t *stream, int span, ftdmchan->physical_chan_id, ss7_info->circuit->cic); - if((sngss7_test_ckt_flag(ss7_info, FLAG_CKT_MN_BLOCK_TX)) || (sngss7_test_ckt_flag(ss7_info, FLAG_GRP_MN_BLOCK_TX))) { + if((sngss7_test_ckt_blk_flag(ss7_info, FLAG_CKT_MN_BLOCK_TX)) || (sngss7_test_ckt_blk_flag(ss7_info, FLAG_GRP_MN_BLOCK_TX))) { stream->write_function(stream, "l_mn=Y|"); }else { stream->write_function(stream, "l_mn=N|"); } - if((sngss7_test_ckt_flag(ss7_info, FLAG_CKT_MN_BLOCK_RX)) || (sngss7_test_ckt_flag(ss7_info, FLAG_GRP_MN_BLOCK_RX))) { + if((sngss7_test_ckt_blk_flag(ss7_info, FLAG_CKT_MN_BLOCK_RX)) || (sngss7_test_ckt_blk_flag(ss7_info, FLAG_GRP_MN_BLOCK_RX))) { stream->write_function(stream, "r_mn=Y|"); }else { stream->write_function(stream, "r_mn=N|"); } - if(sngss7_test_ckt_flag(ss7_info, FLAG_GRP_HW_BLOCK_TX)) { + if(sngss7_test_ckt_blk_flag(ss7_info, FLAG_GRP_HW_BLOCK_TX)) { stream->write_function(stream, "l_hw=Y|"); }else { stream->write_function(stream, "l_hw=N|"); } - if(sngss7_test_ckt_flag(ss7_info, FLAG_GRP_HW_BLOCK_RX)) { + if(sngss7_test_ckt_blk_flag(ss7_info, FLAG_GRP_HW_BLOCK_RX)) { stream->write_function(stream, "r_hw=Y|"); }else { stream->write_function(stream, "r_hw=N|"); } - if(sngss7_test_ckt_flag(ss7_info, FLAG_CKT_LC_BLOCK_RX)) { + if(sngss7_test_ckt_blk_flag(ss7_info, FLAG_CKT_LC_BLOCK_RX)) { stream->write_function(stream, "l_mngmt=Y|"); }else { stream->write_function(stream, "l_mngmt=N|"); } - if(sngss7_test_ckt_flag(ss7_info, FLAG_CKT_UCIC_BLOCK)) { + if(sngss7_test_ckt_blk_flag(ss7_info, FLAG_CKT_UCIC_BLOCK)) { stream->write_function(stream, "l_ucic=Y|"); }else { stream->write_function(stream, "l_ucic=N|"); @@ -1142,48 +1163,47 @@ static ftdm_status_t handle_show_status(ftdm_stream_handle_t *stream, int span, /* grab the signaling_status */ ftdm_channel_get_sig_status(ftdmchan, &sigstatus); - stream->write_function(stream, "span=%2d|chan=%2d|cic=%4d|sig_status=%4s|state=%s|", + stream->write_function(stream, "span=%2d|chan=%2d|cic=%4d|ckt=%4d|sig_status=%4s|state=%s|", ckt->span, ckt->chan, ckt->cic, + ckt->id, ftdm_signaling_status2str(sigstatus), ftdm_channel_state2str(ftdmchan->state)); - if ((sngss7_test_ckt_flag(ss7_info, FLAG_CKT_MN_BLOCK_TX)) || - (sngss7_test_ckt_flag(ss7_info, FLAG_GRP_MN_BLOCK_TX))) { + if ((sngss7_test_ckt_blk_flag(ss7_info, FLAG_CKT_MN_BLOCK_TX)) || + (sngss7_test_ckt_blk_flag(ss7_info, FLAG_GRP_MN_BLOCK_TX))) { stream->write_function(stream, "l_mn=Y|"); }else { stream->write_function(stream, "l_mn=N|"); } - if ((sngss7_test_ckt_flag(ss7_info, FLAG_CKT_MN_BLOCK_RX)) || - (sngss7_test_ckt_flag(ss7_info, FLAG_GRP_MN_BLOCK_RX))) { + if ((sngss7_test_ckt_blk_flag(ss7_info, FLAG_CKT_MN_BLOCK_RX)) || + (sngss7_test_ckt_blk_flag(ss7_info, FLAG_GRP_MN_BLOCK_RX))) { stream->write_function(stream, "r_mn=Y|"); }else { stream->write_function(stream, "r_mn=N|"); } - if (sngss7_test_ckt_flag(ss7_info, FLAG_GRP_HW_BLOCK_TX)) { + if (sngss7_test_ckt_blk_flag(ss7_info, FLAG_GRP_HW_BLOCK_TX)) { stream->write_function(stream, "l_hw=Y|"); }else { stream->write_function(stream, "l_hw=N|"); } - if (sngss7_test_ckt_flag(ss7_info, FLAG_GRP_HW_BLOCK_RX)) { + if (sngss7_test_ckt_blk_flag(ss7_info, FLAG_GRP_HW_BLOCK_RX)) { stream->write_function(stream, "r_hw=Y|"); }else { stream->write_function(stream, "r_hw=N|"); } if (sngss7_test_ckt_flag(ss7_info, FLAG_RELAY_DOWN)) { - stream->write_function(stream, "relay=Y|"); + stream->write_function(stream, "relay=Y"); }else { - stream->write_function(stream, "relay=N|"); + stream->write_function(stream, "relay=N"); } } - - stream->write_function(stream, "flags=0x%X",ss7_info->ckt_flags); - + stream->write_function(stream, "\n"); } /* if ( hole, sig, voice) */ } /* if ( span and chan) */ @@ -1237,10 +1257,10 @@ static ftdm_status_t handle_tx_blo(ftdm_stream_handle_t *stream, int span, int c continue; } else { /* throw the ckt block flag */ - sngss7_set_ckt_flag(ss7_info, FLAG_CKT_MN_BLOCK_TX); + sngss7_set_ckt_blk_flag(ss7_info, FLAG_CKT_MN_BLOCK_TX); /* set the channel to suspended state */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); } /* unlock the channel again before we exit */ @@ -1303,13 +1323,13 @@ static ftdm_status_t handle_tx_ubl(ftdm_stream_handle_t *stream, int span, int c continue; } else { /* throw the ckt block flag */ - sngss7_set_ckt_flag(ss7_info, FLAG_CKT_MN_UNBLK_TX); + sngss7_set_ckt_blk_flag(ss7_info, FLAG_CKT_MN_UNBLK_TX); /* clear the block flag */ - sngss7_clear_ckt_flag(ss7_info, FLAG_CKT_MN_BLOCK_TX); + sngss7_clear_ckt_blk_flag(ss7_info, FLAG_CKT_MN_BLOCK_TX); /* set the channel to suspended state */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); } /* unlock the channel again before we exit */ @@ -1554,12 +1574,12 @@ static ftdm_status_t handle_tx_rsc(ftdm_stream_handle_t *stream, int span, int c /**************************************************************************/ case FTDM_CHANNEL_STATE_RESTART: /* go to idle so that we can redo the restart state*/ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_IDLE); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_IDLE); break; /**************************************************************************/ default: /* set the state of the channel to restart...the rest is done by the chan monitor */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART); break; /**************************************************************************/ } @@ -1627,7 +1647,7 @@ static ftdm_status_t handle_tx_grs(ftdm_stream_handle_t *stream, int span, int c } /* set the channel to suspended state */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART); } @@ -1701,15 +1721,10 @@ static ftdm_status_t handle_tx_cgb(ftdm_stream_handle_t *stream, int span, int c ftdm_mutex_lock(ftdmchan->mutex); /* throw the grp maint. block flag */ - sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_MN_BLOCK_TX); + sngss7_set_ckt_blk_flag(sngss7_info, FLAG_GRP_MN_BLOCK_TX); /* bring the sig status down */ - sigev.chan_id = ftdmchan->chan_id; - sigev.span_id = ftdmchan->span_id; - sigev.channel = ftdmchan; - sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; - sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_DOWN; - ftdm_span_send_signal(ftdmchan->span, &sigev); + sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_DOWN); /* if this is the first channel in the range */ if (ftdmchan->physical_chan_id == chan) { @@ -1801,15 +1816,10 @@ static ftdm_status_t handle_tx_cgu(ftdm_stream_handle_t *stream, int span, int c ftdm_mutex_lock(ftdmchan->mutex); /* throw the grp maint. block flag */ - sngss7_clear_ckt_flag(sngss7_info, FLAG_GRP_MN_BLOCK_TX); + sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_GRP_MN_BLOCK_TX); /* bring the sig status up */ - sigev.chan_id = ftdmchan->chan_id; - sigev.span_id = ftdmchan->span_id; - sigev.channel = ftdmchan; - sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; - sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_UP; - ftdm_span_send_signal(ftdmchan->span, &sigev); + sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_UP); /* if this is the first channel in the range */ if (ftdmchan->physical_chan_id == chan) { @@ -2154,6 +2164,184 @@ success: return FTDM_SUCCESS; } +/******************************************************************************/ +static ftdm_status_t handle_status_isup_ckt(ftdm_stream_handle_t *stream, char *id_name) +{ + sng_isup_ckt_t *ckt; + sngss7_chan_data_t *ss7_info; + ftdm_channel_t *ftdmchan; + uint32_t id; + uint8_t state = 0; + uint8_t bits_ab = 0; + uint8_t bits_cd = 0; + uint8_t bits_ef = 0; + + /* extract the integer version of the id (ckt) */ + id = atoi(id_name); + + /* extract the global config circuit structure */ + ckt = &g_ftdm_sngss7_data.cfg.isupCkt[id]; + + /* confirm the ckt exists */ + if (ckt->id == 0) { + stream->write_function(stream, "Requested ckt does not exist (%d)\n", id); + return FTDM_FAIL; + } + + /* confirm the ckt is a voice channel */ + if (ckt->type != VOICE) { + stream->write_function(stream, "Requested ckt is a sig link/hole and can not be queried (%d)\n", id); + return FTDM_FAIL; + } + + /* extract the global structure */ + ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[id].obj; + ftdmchan = ss7_info->ftdmchan; + + /* query the isup stack for the state of the ckt */ + if (ftmod_ss7_isup_ckt_sta(ckt->id, &state)) { + stream->write_function(stream, "Failed to read isup ckt =%d status\n", id); + return FTDM_FAIL; + } + + + stream->write_function(stream, "span=%2d|chan=%2d|cic=%4d|ckt=%4d|state=0x%02X|", + ckt->span, + ckt->chan, + ckt->cic, + ckt->id, + state); + + /* extract the bit sections */ + bits_ab = (state & (SNG_BIT_A + SNG_BIT_B)) >> 0; + + bits_cd = (state & (SNG_BIT_C + SNG_BIT_D)) >> 2; + + bits_ef = (state & (SNG_BIT_E + SNG_BIT_F)) >> 4; + + /* check bits C and D */ + switch (bits_cd) { + /**************************************************************************/ + case (0): + /* ckt is either un-equipped or transient, check bits A and B */ + switch (bits_ab) { + /**********************************************************************/ + case (0): + /* bit a and bit are cleared, transient */ + stream->write_function(stream, "transient\n"); + goto success; + break; + /**********************************************************************/ + case (1): + case (2): + /* bit a or bit b are set, spare ... shouldn't happen */ + stream->write_function(stream, "spare\n"); + goto success; + break; + /**********************************************************************/ + case (3): + /* bit a and bit b are set, unequipped */ + stream->write_function(stream, "unequipped\n"); + goto success; + break; + /**********************************************************************/ + default: + stream->write_function(stream, "invalid values for bits A and B (%d)\n", + bits_ab); + goto success; + break; + /**********************************************************************/ + } /* switch (bits_ab) */ + + /* shouldn't get here but have a break for properness */ + break; + /**************************************************************************/ + case (1): + /* circuit incoming busy */ + stream->write_function(stream, "incoming busy"); + break; + /**************************************************************************/ + case (2): + /* circuit outgoing busy */ + stream->write_function(stream, "outgoing busy"); + break; + /**************************************************************************/ + case (3): + /* circuit idle */ + stream->write_function(stream, "idle"); + break; + /**************************************************************************/ + default: + /* invalid */ + stream->write_function(stream, "bits C and D are invalid (%d)!\n", + bits_cd); + goto success; + /**************************************************************************/ + } /* switch (bits_cd) */ + + /* check the maintenance block status in bits A and B */ + switch (bits_ab) { + /**************************************************************************/ + case (0): + /* no maintenace block...do nothing */ + break; + /**************************************************************************/ + case (1): + /* locally blocked */ + stream->write_function(stream, "|l_mn"); + break; + /**************************************************************************/ + case (2): + /* remotely blocked */ + stream->write_function(stream, "|r_mn"); + break; + /**************************************************************************/ + case (3): + /* both locally and remotely blocked */ + stream->write_function(stream, "|l_mn|r_mn"); + break; + /**************************************************************************/ + default: + stream->write_function(stream, "bits A and B are invlaid (%d)!\n", + bits_ab); + goto success; + /**************************************************************************/ + } /* switch (bits_ab) */ + + /* check the hardware block status in bits e and f */ + switch (bits_ef) { + /**************************************************************************/ + case (0): + /* no maintenace block...do nothing */ + break; + /**************************************************************************/ + case (1): + /* locally blocked */ + stream->write_function(stream, "|l_hw"); + break; + /**************************************************************************/ + case (2): + /* remotely blocked */ + stream->write_function(stream, "|r_hw"); + break; + /**************************************************************************/ + case (3): + /* both locally and remotely blocked */ + stream->write_function(stream, "|l_hw|r_hw"); + break; + /**************************************************************************/ + default: + stream->write_function(stream, "bits E and F are invlaid (%d)!\n", + bits_ef); + goto success; + /**************************************************************************/ + } /* switch (bits_ef) */ + +success: + stream->write_function(stream, "\n"); + return FTDM_SUCCESS; +} + /******************************************************************************/ static ftdm_status_t extract_span_chan(char *argv[10], int pos, int *span, int *chan) { diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cntrl.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cntrl.c index c1b18e529a..83ef5e0a42 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cntrl.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cntrl.c @@ -68,11 +68,14 @@ int ftmod_ss7_shutdown_isup(void); int ftmod_ss7_shutdown_mtp3(void); int ftmod_ss7_shutdown_mtp2(void); int ftmod_ss7_shutdown_relay(void); +int ftmod_ss7_disable_relay_channel(uint32_t chanId); int ftmod_ss7_disable_grp_mtp3Link(uint32_t procId); int ftmod_ss7_enable_grp_mtp3Link(uint32_t procId); int ftmod_ss7_disable_grp_mtp2Link(uint32_t procId); + +int ftmod_ss7_block_isup_ckt(uint32_t cktId); /******************************************************************************/ /* FUNCTIONS ******************************************************************/ @@ -712,6 +715,38 @@ int ftmod_ss7_shutdown_relay(void) return (sng_cntrl_relay(&pst, &cntrl)); } +/******************************************************************************/ +int ftmod_ss7_disable_relay_channel(uint32_t chanId) +{ + RyMngmt cntrl; + Pst pst; + + /* initalize the post structure */ + smPstInit(&pst); + + /* insert the destination Entity */ + pst.dstEnt = ENTRY; + + /* initalize the control structure */ + memset(&cntrl, 0x0, sizeof(RyMngmt)); + + /* initalize the control header */ + smHdrInit(&cntrl.hdr); + + cntrl.hdr.msgType = TCNTRL; /* this is a control request */ + cntrl.hdr.entId.ent = ENTRY; + cntrl.hdr.entId.inst = S_INST; + cntrl.hdr.elmId.elmnt = STGEN; + + + cntrl.hdr.elmId.elmntInst1 = chanId; + + cntrl.t.cntrl.action = ADISIMM; /* Deactivate */ + cntrl.t.cntrl.subAction = SAELMNT; /* specificed element */ + + return (sng_cntrl_relay(&pst, &cntrl)); +} + /******************************************************************************/ int ftmod_ss7_disable_grp_mtp3Link(uint32_t procId) { @@ -808,6 +843,38 @@ int ftmod_ss7_disable_grp_mtp2Link(uint32_t procId) } +/******************************************************************************/ +int ftmod_ss7_block_isup_ckt(uint32_t cktId) +{ + SiMngmt cntrl; + Pst pst; + + /* initalize the post structure */ + smPstInit(&pst); + + /* insert the destination Entity */ + pst.dstEnt = ENTSI; + + /* initalize the control structure */ + memset(&cntrl, 0x0, sizeof(SiMngmt)); + + /* initalize the control header */ + smHdrInit(&cntrl.hdr); + + cntrl.hdr.msgType = TCNTRL; /* this is a control request */ + cntrl.hdr.entId.ent = ENTSI; + cntrl.hdr.entId.inst = S_INST; + cntrl.hdr.elmId.elmnt = STICIR; + + cntrl.t.cntrl.s.siElmnt.elmntId.circuit = cktId; + cntrl.t.cntrl.s.siElmnt.elmntParam.cir.flag = LSI_CNTRL_CIR_FORCE; + + cntrl.t.cntrl.action = ADISIMM; /* block via BLO */ + cntrl.t.cntrl.subAction = SAELMNT; /* specificed element */ + + return (sng_cntrl_isup(&pst, &cntrl)); +} + /******************************************************************************/ /* For Emacs: * Local Variables: diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c index 3a6fca7376..e0b6ae08c0 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c @@ -101,19 +101,17 @@ ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ if (sngss7_test_ckt_flag(sngss7_info, FLAG_GLARE)) { SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx IAM (glare)\n", sngss7_info->circuit->cic); - } else { - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx IAM\n", sngss7_info->circuit->cic); - } + } /* check if the circuit has a remote block */ - if ((sngss7_test_ckt_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) || - (sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX)) || - (sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX))) { + if ((sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) || + (sngss7_test_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX)) || + (sngss7_test_ckt_blk_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX))) { /* as per Q.764, 2.8.2.3 xiv ... remove the block from this channel */ - sngss7_clear_ckt_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX); - sngss7_clear_ckt_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX); - sngss7_clear_ckt_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX); + sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX); + sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX); + sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX); /* KONRAD FIX ME : check in case there is a ckt and grp block */ } @@ -139,7 +137,7 @@ ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ ftdmchan->caller_data.hangup_cause = 41; /* move the state to CANCEL */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_CANCEL); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_CANCEL); } else { @@ -211,11 +209,10 @@ ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ /* add any special variables for the dialplan */ sprintf(nadi, "%d", siConEvnt->cgPtyNum.natAddrInd.val); - ftdm_call_add_var(&ftdmchan->caller_data, "ss7_clg_nadi", nadi); + sngss7_add_var(sngss7_info, "ss7_clg_nadi", nadi); sprintf(nadi, "%d", siConEvnt->cdPtyNum.natAddrInd.val); - ftdm_call_add_var(&ftdmchan->caller_data, "ss7_cld_nadi", nadi); - + sngss7_add_var(sngss7_info, "ss7_cld_nadi", nadi); /* check if a COT test is requested */ if ((siConEvnt->natConInd.eh.pres) && @@ -228,12 +225,19 @@ ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ ftdm_channel_command(ftdmchan, FTDM_COMMAND_ENABLE_LOOP, NULL); /* move to in loop state */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_IN_LOOP); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_IN_LOOP); } else { /* set the state of the channel to collecting...the rest is done by the chan monitor */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_COLLECT); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_COLLECT); } + SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx IAM clg = \"%s\" (NADI=%d), cld = \"%s\" (NADI=%d)\n", + sngss7_info->circuit->cic, + ftdmchan->caller_data.cid_num.digits, + siConEvnt->cgPtyNum.natAddrInd.val, + ftdmchan->caller_data.dnis.digits, + siConEvnt->cdPtyNum.natAddrInd.val); + } /* if (channel is usable */ break; @@ -264,7 +268,7 @@ handle_glare: sngss7_set_ckt_flag(sngss7_info, FLAG_REMOTE_REL); /* move the state of the channel to Terminating to end the call */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); } /* if (!(sngss7_test_ckt_flag(sngss7_info, FLAG_GLARE))) */ break; /**************************************************************************/ @@ -275,7 +279,7 @@ handle_glare: sngss7_set_ckt_flag(sngss7_info, FLAG_RESET_TX); /* move the state of the channel to RESTART to force a reset */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART); break; /**************************************************************************/ @@ -324,14 +328,14 @@ ftdm_status_t handle_con_sta(uint32_t suInstId, uint32_t spInstId, uint32_t circ if (siCnStEvnt->optBckCalInd.inbndInfoInd.val) { /* go to PROGRESS_MEDIA */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA); } else { /* go to PROGRESS */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS); } /* if (inband) */ } else { /* go to PROGRESS_MEDIA */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA); } break; @@ -344,7 +348,7 @@ ftdm_status_t handle_con_sta(uint32_t suInstId, uint32_t spInstId, uint32_t circ sngss7_set_ckt_flag(sngss7_info, FLAG_RESET_TX); /* go to RESTART */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART); break; /**********************************************************************/ } /* switch (ftdmchan->state) */ @@ -398,7 +402,7 @@ ftdm_status_t handle_con_sta(uint32_t suInstId, uint32_t spInstId, uint32_t circ } /* go to idle so that collect state is processed again */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_IDLE); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_IDLE); break; /**********************************************************************/ @@ -527,7 +531,7 @@ ftdm_status_t handle_con_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circ SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx ANM\n", sngss7_info->circuit->cic); /* go to UP */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_UP); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_UP); break; /**************************************************************************/ @@ -536,7 +540,7 @@ ftdm_status_t handle_con_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circ SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx CON\n", sngss7_info->circuit->cic); /* go to UP */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_UP); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_UP); break; /**************************************************************************/ @@ -548,7 +552,7 @@ ftdm_status_t handle_con_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circ sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_TX); /* go to RESTART */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART); break; /**************************************************************************/ @@ -600,7 +604,7 @@ ftdm_status_t handle_rel_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ sngss7_set_ckt_flag(sngss7_info, FLAG_REMOTE_REL); ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_LOOP, NULL); /* move the state of the channel to CANCEL to end the call */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); break; /**************************************************************************/ @@ -621,7 +625,7 @@ ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_LOOP, NULL); sngss7_set_ckt_flag(sngss7_info, FLAG_REMOTE_REL); /* move the state of the channel to TERMINATING to end the call */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); break; /**************************************************************************/ @@ -634,7 +638,7 @@ ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_LOOP, NULL); sngss7_set_ckt_flag(sngss7_info, FLAG_REMOTE_REL); /* go to hangup complete to send the RLC */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE); /* save the call info for the RLC */ sngss7_info->suInstId = get_unique_id(); @@ -648,7 +652,7 @@ ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_LOOP, NULL); sngss7_set_ckt_flag(sngss7_info, FLAG_RESET_RX); /* set the state to RESTART */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART); break; /**************************************************************************/ } /* switch (ftdmchan->state) */ @@ -687,7 +691,7 @@ ftdm_status_t handle_rel_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circ case FTDM_CHANNEL_STATE_HANGUP_COMPLETE: /* go to DOWN */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); break; /**************************************************************************/ @@ -699,7 +703,7 @@ ftdm_status_t handle_rel_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circ /* KONRAD: should just stop the call...but a reset is easier for now (since it does hangup the call) */ /* go to RESTART */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART); break; /**************************************************************************/ @@ -877,232 +881,187 @@ ftdm_status_t handle_resm_ind(uint32_t suInstId, uint32_t spInstId, uint32_t cir /******************************************************************************/ ftdm_status_t handle_sta_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) { - sngss7_chan_data_t *sngss7_info ; - ftdm_channel_t *ftdmchan; + SS7_FUNC_TRACE_ENTER(__FUNCTION__); - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); + /* confirm that the circuit is active on our side otherwise move to the next circuit */ + if (!sngss7_test_flag(&g_ftdm_sngss7_data.cfg.isupCkt[circuit], SNGSS7_ACTIVE)) { + SS7_ERROR("[CIC:%d]Rx %s but circuit is not active yet, skipping!\n", + g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, + DECODE_LCC_EVENT(evntType)); return FTDM_FAIL; } - SS7_FUNC_TRACE_ENTER(__FUNCTION__); - switch (evntType) { /**************************************************************************/ case SIT_STA_REATTEMPT: /* reattempt indication */ - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx Reattempt indication\n", sngss7_info->circuit->cic); handle_reattempt(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); break; /**************************************************************************/ case SIT_STA_ERRORIND: /* error indication */ - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx Error indication\n", sngss7_info->circuit->cic); SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); break; /**************************************************************************/ case SIT_STA_CONTCHK: /* continuity check */ - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx CCR start\n", sngss7_info->circuit->cic); handle_cot_start(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); break; /**************************************************************************/ case SIT_STA_CONTREP: /* continuity report */ - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx COT report\n", sngss7_info->circuit->cic); handle_cot(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); break; /**************************************************************************/ case SIT_STA_STPCONTIN: /* stop continuity */ - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx CCR stop\n", sngss7_info->circuit->cic); handle_cot_stop(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); break; /**************************************************************************/ case SIT_STA_CGQRYRSP: /* circuit grp query response from far end forwarded to upper layer by ISUP */ - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx CQM\n", sngss7_info->circuit->cic); SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); break; /**************************************************************************/ case SIT_STA_CONFUSION: /* confusion */ - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx CFN\n", sngss7_info->circuit->cic); SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); break; /**************************************************************************/ case SIT_STA_LOOPBACKACK: /* loop-back acknowledge */ - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx LPA\n", sngss7_info->circuit->cic); SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); break; /**************************************************************************/ case SIT_STA_CIRRSRVREQ: /* circuit reservation request */ - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx Ckt Resveration req\n", sngss7_info->circuit->cic); SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); break; /**************************************************************************/ case SIT_STA_CIRRSRVACK: /* circuit reservation acknowledgement */ - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx Ckt Res ack\n", sngss7_info->circuit->cic); SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); break; /**************************************************************************/ case SIT_STA_CIRBLOREQ: /* circuit blocking request */ - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx BLO\n", sngss7_info->circuit->cic); handle_blo_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); break; /**************************************************************************/ case SIT_STA_CIRBLORSP: /* circuit blocking response */ - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx BLA\n", sngss7_info->circuit->cic); handle_blo_rsp(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); break; /**************************************************************************/ case SIT_STA_CIRUBLREQ: /* circuit unblocking request */ - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx UBL\n", sngss7_info->circuit->cic); handle_ubl_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); break; /**************************************************************************/ case SIT_STA_CIRUBLRSP: /* circuit unblocking response */ - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx UBA\n", sngss7_info->circuit->cic); handle_ubl_rsp(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); break; /**************************************************************************/ case SIT_STA_CIRRESREQ: /* circuit reset request - RSC */ - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx RSC\n", sngss7_info->circuit->cic); handle_rsc_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); break; /**************************************************************************/ case SIT_STA_CIRLOCRES: /* reset initiated locally by the software */ - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx Local RSC\n", sngss7_info->circuit->cic); handle_local_rsc_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); break; /**************************************************************************/ case SIT_STA_CIRRESRSP: /* circuit reset response */ - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx RSC-RLC\n", sngss7_info->circuit->cic); handle_rsc_rsp(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); break; /**************************************************************************/ case SIT_STA_CGBREQ: /* CGB request */ - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx CGB\n", sngss7_info->circuit->cic); handle_cgb_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); break; /**************************************************************************/ case SIT_STA_CGUREQ: /* CGU request */ - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx CGU\n", sngss7_info->circuit->cic); handle_cgu_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); break; /**************************************************************************/ case SIT_STA_CGQRYREQ: /* circuit group query request */ - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx CQM\n", sngss7_info->circuit->cic); SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); break; /**************************************************************************/ case SIT_STA_CGBRSP: /* mntc. oriented CGB response */ - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx mntc CGB\n", sngss7_info->circuit->cic); /*handle_cgb_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt);*/ break; /**************************************************************************/ case SIT_STA_CGURSP: /* mntc. oriented CGU response */ - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx mntc CGU\n", sngss7_info->circuit->cic); /*SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));*/ break; /**************************************************************************/ case SIT_STA_GRSREQ: /* circuit group reset request */ - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx GRS\n", sngss7_info->circuit->cic); handle_grs_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); break; /**************************************************************************/ case SIT_STA_CIRUNEQPD: /* circuit unequipped indication */ - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx UCIC\n", sngss7_info->circuit->cic); handle_ucic(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); break; /**************************************************************************/ case SIT_STA_GRSRSP: /* circuit group reset response */ - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx GRA\n", sngss7_info->circuit->cic); handle_grs_rsp(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); break; /**************************************************************************/ case SIT_STA_PAUSEIND: /* pause indication */ - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx SUS\n", sngss7_info->circuit->cic); handle_pause(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); break; /**************************************************************************/ case SIT_STA_RESUMEIND: /* resume indication */ - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx RES\n", sngss7_info->circuit->cic); handle_resume(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); break; /**************************************************************************/ case SIT_STA_USRPARTA: /* user part available */ - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx UPA\n", sngss7_info->circuit->cic); SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); break; /**************************************************************************/ case SIT_STA_RMTUSRUNAV: /* remote user not available */ - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx Remote User not Available\n", sngss7_info->circuit->cic); SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); break; /**************************************************************************/ case SIT_STA_MTPCONG0: /* congestion indication level 0 */ - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx Congestion L0\n", sngss7_info->circuit->cic); SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); break; /**************************************************************************/ case SIT_STA_MTPCONG1: /* congestion indication level 1 */ - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx Congestion L1\n", sngss7_info->circuit->cic); SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); break; /**************************************************************************/ case SIT_STA_MTPCONG2: /* congestion indication level 2 */ - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx Congestion L2\n", sngss7_info->circuit->cic); SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); break; /**************************************************************************/ case SIT_STA_MTPCONG3: /* congestion indication level 3 */ - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx Congestion L3\n", sngss7_info->circuit->cic); SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); break; /**************************************************************************/ case SIT_STA_MTPSTPCONG: /* stop congestion indication level 0 */ - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx Stop Congestion\n", sngss7_info->circuit->cic); SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); break; /**************************************************************************/ case SIT_STA_CIRLOCALBLOIND: /* Mngmt local blocking */ - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx Local BLO\n", sngss7_info->circuit->cic); handle_local_blk(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); break; /**************************************************************************/ case SIT_STA_CIRLOCALUBLIND: /* Mngmt local unblocking */ - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx Local UBL\n", sngss7_info->circuit->cic); handle_local_ubl(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); break; /**************************************************************************/ case SIT_STA_OVERLOAD: /* Overload */ - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx Overload\n", sngss7_info->circuit->cic); handle_olm_msg(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); break; /**************************************************************************/ case SIT_STA_LMCGBREQ: /* when LM requests ckt grp blocking */ - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx LM CGB\n", sngss7_info->circuit->cic); SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); break; /**************************************************************************/ case SIT_STA_LMCGUREQ: /* when LM requests ckt grp unblocking */ - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx LM CGU\n", sngss7_info->circuit->cic); SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); break; /**************************************************************************/ case SIT_STA_LMGRSREQ: /* when LM requests ckt grp reset */ - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx LM RSC\n", sngss7_info->circuit->cic); SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); break; /**************************************************************************/ case SIT_STA_CGBINFOIND: /* circuit grp blking ind , no resp req */ - /*SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx CGB no resp req\n", sngss7_info->circuit->cic);*/ /* handle_cgb_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt);*/ break; /**************************************************************************/ case SIT_STA_LMCQMINFOREQ: /* when LM requests ckt grp query */ - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx LM CQM\n", sngss7_info->circuit->cic); // SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); break; /**************************************************************************/ case SIT_STA_CIRLOCGRS: /* group reset initiated locally by the software */ - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx Local GRS\n", sngss7_info->circuit->cic); SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); break; /**************************************************************************/ @@ -1124,11 +1083,25 @@ ftdm_status_t handle_reattempt(uint32_t suInstId, uint32_t spInstId, uint32_t ci sngss7_chan_data_t *sngss7_info = NULL; ftdm_channel_t *ftdmchan = NULL; - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for ISUP circuit = %d!\n", circuit); + /* confirm that the circuit is voice channel */ + if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != VOICE) { + SS7_ERROR("[CIC:%d]Rx %s on non-voice CIC\n", + g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, + DECODE_LCC_EVENT(evntType)); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); return FTDM_FAIL; + } else { + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for ISUP circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + SS7_INFO_CHAN(ftdmchan, "[CIC:%d]Rx %s\n", + g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, + DECODE_LCC_EVENT(evntType)); } /* lock the channel */ @@ -1152,7 +1125,7 @@ ftdm_status_t handle_reattempt(uint32_t suInstId, uint32_t spInstId, uint32_t ci sngss7_set_ckt_flag(sngss7_info, FLAG_REMOTE_REL); /* move the state of the channel to Terminating to end the call */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); } /* unlock the channel again before we exit */ @@ -1185,6 +1158,13 @@ ftdm_status_t handle_pause(uint32_t suInstId, uint32_t spInstId, uint32_t circui /* check that the infId matches and that this is not a siglink */ if ((g_ftdm_sngss7_data.cfg.isupCkt[i].infId == infId) && (g_ftdm_sngss7_data.cfg.isupCkt[i].type == VOICE)) { + + /* confirm that the circuit is active on our side otherwise move to the next circuit */ + if (!sngss7_test_flag(&g_ftdm_sngss7_data.cfg.isupCkt[i], SNGSS7_ACTIVE)) { + SS7_ERROR("[CIC:%d]Circuit is not active yet, skipping!\n",g_ftdm_sngss7_data.cfg.isupCkt[i].cic); + i++; + continue; + } /* get the ftdmchan and ss7_chan_data from the circuit */ if (extract_chan_data(i, &sngss7_info, &ftdmchan)) { @@ -1201,6 +1181,9 @@ ftdm_status_t handle_pause(uint32_t suInstId, uint32_t spInstId, uint32_t circui SS7_DEBUG_CHAN(ftdmchan, "Rx PAUSE%s\n", ""); /* set the pause flag on the channel */ sngss7_set_ckt_flag(sngss7_info, FLAG_INFID_PAUSED); + + /* clear the resume flag on the channel */ + sngss7_set_ckt_flag(sngss7_info, FLAG_INFID_RESUME); } /* unlock the channel again before we exit */ @@ -1241,6 +1224,13 @@ ftdm_status_t handle_resume(uint32_t suInstId, uint32_t spInstId, uint32_t circu if ((g_ftdm_sngss7_data.cfg.isupCkt[i].infId == infId) && (g_ftdm_sngss7_data.cfg.isupCkt[i].type == VOICE)) { + /* confirm that the circuit is active on our side otherwise move to the next circuit */ + if (!sngss7_test_flag(&g_ftdm_sngss7_data.cfg.isupCkt[i], SNGSS7_ACTIVE)) { + SS7_ERROR("[CIC:%d]Circuit is not active yet, skipping!\n",g_ftdm_sngss7_data.cfg.isupCkt[i].cic); + i++; + continue; + } + /* get the ftdmchan and ss7_chan_data from the circuit */ if (extract_chan_data(i, &sngss7_info, &ftdmchan)) { SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); @@ -1284,11 +1274,25 @@ ftdm_status_t handle_cot_start(uint32_t suInstId, uint32_t spInstId, uint32_t ci sngss7_chan_data_t *sngss7_info = NULL; ftdm_channel_t *ftdmchan = NULL; - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + /* confirm that the circuit is voice channel */ + if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != VOICE) { + SS7_ERROR("[CIC:%d]Rx %s on non-voice CIC\n", + g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, + DECODE_LCC_EVENT(evntType)); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); return FTDM_FAIL; + } else { + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for ISUP circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + SS7_INFO_CHAN(ftdmchan, "[CIC:%d]Rx %s\n", + g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, + DECODE_LCC_EVENT(evntType)); } /* lock the channel */ @@ -1308,7 +1312,7 @@ ftdm_status_t handle_cot_start(uint32_t suInstId, uint32_t spInstId, uint32_t ci ftdm_channel_command(ftdmchan, FTDM_COMMAND_ENABLE_LOOP, NULL); /* switch to the IN_LOOP state */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_IN_LOOP); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_IN_LOOP); /* unlock the channel again before we exit */ ftdm_mutex_unlock(ftdmchan->mutex); @@ -1325,11 +1329,25 @@ ftdm_status_t handle_cot_stop(uint32_t suInstId, uint32_t spInstId, uint32_t cir sngss7_chan_data_t *sngss7_info = NULL; ftdm_channel_t *ftdmchan = NULL; - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + /* confirm that the circuit is voice channel */ + if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != VOICE) { + SS7_ERROR("[CIC:%d]Rx %s on non-voice CIC\n", + g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, + DECODE_LCC_EVENT(evntType)); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); return FTDM_FAIL; + } else { + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for ISUP circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + SS7_INFO_CHAN(ftdmchan, "[CIC:%d]Rx %s\n", + g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, + DECODE_LCC_EVENT(evntType)); } /* lock the channel */ @@ -1339,7 +1357,7 @@ ftdm_status_t handle_cot_stop(uint32_t suInstId, uint32_t spInstId, uint32_t cir ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_LOOP, NULL); /* exit out of the LOOP state to the last state */ - ftdm_set_state_locked(ftdmchan, ftdmchan->last_state); + ftdm_set_state(ftdmchan, ftdmchan->last_state); /* unlock the channel again before we exit */ ftdm_mutex_unlock(ftdmchan->mutex); @@ -1356,11 +1374,25 @@ ftdm_status_t handle_cot(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, sngss7_chan_data_t *sngss7_info = NULL; ftdm_channel_t *ftdmchan = NULL; - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + /* confirm that the circuit is voice channel */ + if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != VOICE) { + SS7_ERROR("[CIC:%d]Rx %s on non-voice CIC\n", + g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, + DECODE_LCC_EVENT(evntType)); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); return FTDM_FAIL; + } else { + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for ISUP circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + SS7_INFO_CHAN(ftdmchan, "[CIC:%d]Rx %s\n", + g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, + DECODE_LCC_EVENT(evntType)); } /* lock the channel */ @@ -1373,13 +1405,13 @@ ftdm_status_t handle_cot(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_LOOP, NULL); /* exit out of the LOOP state and go to collect */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_COLLECT); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_COLLECT); break; /**************************************************************************/ default: /* exit out of the LOOP state to the last state */ - ftdm_set_state_locked(ftdmchan, ftdmchan->last_state); + ftdm_set_state(ftdmchan, ftdmchan->last_state); break; /**************************************************************************/ @@ -1410,26 +1442,40 @@ ftdm_status_t handle_blo_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ sngss7_chan_data_t *sngss7_info = NULL; ftdm_channel_t *ftdmchan = NULL; - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + /* confirm that the circuit is voice channel */ + if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != VOICE) { + SS7_ERROR("[CIC:%d]Rx %s on non-voice CIC\n", + g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, + DECODE_LCC_EVENT(evntType)); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); return FTDM_FAIL; + } else { + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for ISUP circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + SS7_INFO_CHAN(ftdmchan, "[CIC:%d]Rx %s\n", + g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, + DECODE_LCC_EVENT(evntType)); } /* lock the channel */ ftdm_mutex_lock(ftdmchan->mutex); /* check if the circuit is already blocked or not */ - if (sngss7_test_ckt_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) { + if (sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) { SS7_WARN("Received BLO on circuit that is already blocked!\n"); } /* throw the ckt block flag */ - sngss7_set_ckt_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX); + sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX); /* set the channel to suspended state */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); /* unlock the channel again before we exit */ ftdm_mutex_unlock(ftdmchan->mutex); @@ -1446,11 +1492,25 @@ ftdm_status_t handle_blo_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circ sngss7_chan_data_t *sngss7_info = NULL; ftdm_channel_t *ftdmchan = NULL; - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + /* confirm that the circuit is voice channel */ + if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != VOICE) { + SS7_ERROR("[CIC:%d]Rx %s on non-voice CIC\n", + g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, + DECODE_LCC_EVENT(evntType)); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); return FTDM_FAIL; + } else { + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for ISUP circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + SS7_INFO_CHAN(ftdmchan, "[CIC:%d]Rx %s\n", + g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, + DECODE_LCC_EVENT(evntType)); } /* lock the channel */ @@ -1473,29 +1533,43 @@ ftdm_status_t handle_ubl_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ sngss7_chan_data_t *sngss7_info = NULL; ftdm_channel_t *ftdmchan = NULL; - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + /* confirm that the circuit is voice channel */ + if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != VOICE) { + SS7_ERROR("[CIC:%d]Rx %s on non-voice CIC\n", + g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, + DECODE_LCC_EVENT(evntType)); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); return FTDM_FAIL; + } else { + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for ISUP circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + SS7_INFO_CHAN(ftdmchan, "[CIC:%d]Rx %s\n", + g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, + DECODE_LCC_EVENT(evntType)); } /* lock the channel */ ftdm_mutex_lock(ftdmchan->mutex); /* check if the channel is blocked */ - if (!(sngss7_test_ckt_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX))) { + if (!(sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX))) { SS7_WARN("Received UBL on circuit that is not blocked!\n"); } /* throw the unblock flag */ - sngss7_set_ckt_flag(sngss7_info, FLAG_CKT_MN_UNBLK_RX); + sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_UNBLK_RX); /* clear the block flag */ - sngss7_clear_ckt_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX); + sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX); /* set the channel to suspended state */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); /* unlock the channel again before we exit */ ftdm_mutex_unlock(ftdmchan->mutex); @@ -1512,11 +1586,25 @@ ftdm_status_t handle_ubl_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circ sngss7_chan_data_t *sngss7_info = NULL; ftdm_channel_t *ftdmchan = NULL; - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + /* confirm that the circuit is voice channel */ + if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != VOICE) { + SS7_ERROR("[CIC:%d]Rx %s on non-voice CIC\n", + g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, + DECODE_LCC_EVENT(evntType)); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); return FTDM_FAIL; + } else { + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for ISUP circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + SS7_INFO_CHAN(ftdmchan, "[CIC:%d]Rx %s\n", + g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, + DECODE_LCC_EVENT(evntType)); } /* lock the channel */ @@ -1539,11 +1627,25 @@ ftdm_status_t handle_rsc_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ sngss7_chan_data_t *sngss7_info = NULL; ftdm_channel_t *ftdmchan = NULL; - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + /* confirm that the circuit is voice channel */ + if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != VOICE) { + SS7_ERROR("[CIC:%d]Rx %s on non-voice CIC\n", + g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, + DECODE_LCC_EVENT(evntType)); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); return FTDM_FAIL; + } else { + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for ISUP circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + SS7_INFO_CHAN(ftdmchan, "[CIC:%d]Rx %s\n", + g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, + DECODE_LCC_EVENT(evntType)); } /* lock the channel */ @@ -1557,14 +1659,14 @@ ftdm_status_t handle_rsc_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ case FTDM_CHANNEL_STATE_RESTART: /* go to idle so that we can redo the restart state*/ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_IDLE); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_IDLE); break; /**************************************************************************/ default: /* set the state of the channel to restart...the rest is done by the chan monitor */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART); break; /**************************************************************************/ } @@ -1584,13 +1686,26 @@ ftdm_status_t handle_local_rsc_req(uint32_t suInstId, uint32_t spInstId, uint32_ sngss7_chan_data_t *sngss7_info = NULL; ftdm_channel_t *ftdmchan = NULL; - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + /* confirm that the circuit is voice channel */ + if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != VOICE) { + SS7_ERROR("[CIC:%d]Rx %s on non-voice CIC\n", + g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, + DECODE_LCC_EVENT(evntType)); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); return FTDM_FAIL; - } + } else { + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for ISUP circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + SS7_INFO_CHAN(ftdmchan, "[CIC:%d]Rx %s\n", + g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, + DECODE_LCC_EVENT(evntType)); + } /* lock the channel */ ftdm_mutex_lock(ftdmchan->mutex); @@ -1602,14 +1717,14 @@ ftdm_status_t handle_local_rsc_req(uint32_t suInstId, uint32_t spInstId, uint32_ case FTDM_CHANNEL_STATE_RESTART: /* go to idle so that we can redo the restart state*/ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_IDLE); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_IDLE); break; /**************************************************************************/ default: /* set the state of the channel to restart...the rest is done by the chan monitor */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART); break; /**************************************************************************/ } @@ -1629,11 +1744,25 @@ ftdm_status_t handle_rsc_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circ sngss7_chan_data_t *sngss7_info = NULL; ftdm_channel_t *ftdmchan = NULL; - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + /* confirm that the circuit is voice channel */ + if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != VOICE) { + SS7_ERROR("[CIC:%d]Rx %s on non-voice CIC\n", + g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, + DECODE_LCC_EVENT(evntType)); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); return FTDM_FAIL; + } else { + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for ISUP circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + SS7_INFO_CHAN(ftdmchan, "[CIC:%d]Rx %s\n", + g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, + DECODE_LCC_EVENT(evntType)); } /* lock the channel */ @@ -1648,7 +1777,7 @@ ftdm_status_t handle_rsc_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circ sngss7_set_ckt_flag(sngss7_info, FLAG_RESET_TX_RSP); /* go to DOWN */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); } else { SS7_ERROR("Received RSC-RLC but we're not waiting on a RSC-RLC on CIC #, dropping\n", sngss7_info->circuit->cic); } @@ -1670,7 +1799,7 @@ ftdm_status_t handle_rsc_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circ sngss7_set_ckt_flag(sngss7_info, FLAG_RESET_TX_RSP); /* go to DOWN */ - /*ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);*/ + /*ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);*/ break; /**********************************************************************/ @@ -1684,7 +1813,7 @@ ftdm_status_t handle_rsc_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circ ftdmchan->caller_data.hangup_cause = 98; /* Message not compatiable with call state */ } - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); break; /**********************************************************************/ } @@ -1706,10 +1835,25 @@ ftdm_status_t handle_grs_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ int range; - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + /* confirm that the circuit is voice channel */ + if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != VOICE) { + SS7_ERROR("[CIC:%d]Rx %s on non-voice CIC\n", + g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, + DECODE_LCC_EVENT(evntType)); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); return FTDM_FAIL; + } else { + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for ISUP circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + SS7_INFO_CHAN(ftdmchan, "[CIC:%d]Rx %s\n", + g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, + DECODE_LCC_EVENT(evntType)); } /* extract the range value from the event structure */ @@ -1742,10 +1886,25 @@ ftdm_status_t handle_grs_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circ sngss7_span_data_t *sngss7_span = NULL; int range; - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + /* confirm that the circuit is voice channel */ + if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != VOICE) { + SS7_ERROR("[CIC:%d]Rx %s on non-voice CIC\n", + g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, + DECODE_LCC_EVENT(evntType)); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); return FTDM_FAIL; + } else { + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for ISUP circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + SS7_INFO_CHAN(ftdmchan, "[CIC:%d]Rx %s\n", + g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, + DECODE_LCC_EVENT(evntType)); } /* extract the range value from the event structure */ @@ -1784,26 +1943,40 @@ ftdm_status_t handle_local_blk(uint32_t suInstId, uint32_t spInstId, uint32_t ci sngss7_chan_data_t *sngss7_info = NULL; ftdm_channel_t *ftdmchan = NULL; - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + /* confirm that the circuit is voice channel */ + if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != VOICE) { + SS7_ERROR("[CIC:%d]Rx %s on non-voice CIC\n", + g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, + DECODE_LCC_EVENT(evntType)); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); return FTDM_FAIL; + } else { + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for ISUP circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + SS7_INFO_CHAN(ftdmchan, "[CIC:%d]Rx %s\n", + g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, + DECODE_LCC_EVENT(evntType)); } /* lock the channel */ ftdm_mutex_lock(ftdmchan->mutex); /* check if the circuit is already blocked or not */ - if (sngss7_test_ckt_flag(sngss7_info, FLAG_CKT_LC_BLOCK_RX)) { + if (sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_LC_BLOCK_RX)) { SS7_WARN("Received local BLO on circuit that is already blocked!\n"); } /* throw the ckt block flag */ - sngss7_set_ckt_flag(sngss7_info, FLAG_CKT_LC_BLOCK_RX); + sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_LC_BLOCK_RX); /* set the channel to suspended state */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); /* unlock the channel again before we exit */ ftdm_mutex_unlock(ftdmchan->mutex); @@ -1820,26 +1993,40 @@ ftdm_status_t handle_local_ubl(uint32_t suInstId, uint32_t spInstId, uint32_t ci sngss7_chan_data_t *sngss7_info = NULL; ftdm_channel_t *ftdmchan = NULL; - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + /* confirm that the circuit is voice channel */ + if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != VOICE) { + SS7_ERROR("[CIC:%d]Rx %s on non-voice CIC\n", + g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, + DECODE_LCC_EVENT(evntType)); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); return FTDM_FAIL; + } else { + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for ISUP circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + SS7_INFO_CHAN(ftdmchan, "[CIC:%d]Rx %s\n", + g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, + DECODE_LCC_EVENT(evntType)); } /* lock the channel */ ftdm_mutex_lock(ftdmchan->mutex); /* check if the circuit is already blocked or not */ - if (sngss7_test_ckt_flag(sngss7_info, FLAG_CKT_LC_UNBLK_RX)) { + if (sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_LC_UNBLK_RX)) { SS7_WARN("Received local UBL on circuit that is already unblocked!\n"); } /* throw the ckt block flag */ - sngss7_set_ckt_flag(sngss7_info, FLAG_CKT_LC_UNBLK_RX); + sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_LC_UNBLK_RX); /* set the channel to suspended state */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); /* unlock the channel again before we exit */ ftdm_mutex_unlock(ftdmchan->mutex); @@ -1858,11 +2045,25 @@ ftdm_status_t handle_ucic(uint32_t suInstId, uint32_t spInstId, uint32_t circuit ftdm_channel_t *ftdmchan = NULL; - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + /* confirm that the circuit is voice channel */ + if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != VOICE) { + SS7_ERROR("[CIC:%d]Rx %s on non-voice CIC\n", + g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, + DECODE_LCC_EVENT(evntType)); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); return FTDM_FAIL; + } else { + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for ISUP circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + SS7_INFO_CHAN(ftdmchan, "[CIC:%d]Rx %s\n", + g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, + DECODE_LCC_EVENT(evntType)); } /* check if we just sent a GRS request...*/ @@ -1878,10 +2079,10 @@ ftdm_status_t handle_ucic(uint32_t suInstId, uint32_t spInstId, uint32_t circuit ftdm_mutex_lock(ftdmchan->mutex); /* throw the ckt block flag */ - sngss7_set_ckt_flag(sngss7_info, FLAG_CKT_UCIC_BLOCK); + sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_UCIC_BLOCK); /* set the channel to suspended state */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); /* unlock the channel again before we exit */ ftdm_mutex_unlock(ftdmchan->mutex); @@ -1904,18 +2105,29 @@ ftdm_status_t handle_cgb_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ int byte = 0; int bit = 0; int x; - ftdm_sigmsg_t sigev; - memset(&sigev, 0, sizeof (sigev)); memset(&status[0], '\0', sizeof(status)); - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + /* confirm that the circuit is voice channel */ + if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != VOICE) { + SS7_ERROR("[CIC:%d]Rx %s on non-voice CIC\n", + g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, + DECODE_LCC_EVENT(evntType)); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); return FTDM_FAIL; - } + } else { + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for ISUP circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + SS7_INFO_CHAN(ftdmchan, "[CIC:%d]Rx %s\n", + g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, + DECODE_LCC_EVENT(evntType)); + } /* grab the span info */ sngss7_span = ftdmchan->span->signal_data; @@ -1982,11 +2194,11 @@ ftdm_status_t handle_cgb_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ switch (blockType) { /**********************************************************************/ case 0: /* maintenance oriented */ - sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX); + sngss7_set_ckt_blk_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX); break; /**********************************************************************/ case 1: /* hardware failure oriented */ - sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX); + sngss7_set_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX); break; /**********************************************************************/ case 2: /* reserved for national use */ @@ -1998,14 +2210,8 @@ ftdm_status_t handle_cgb_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ } /* switch (blockType) */ } - sigev.chan_id = ftdmchan->chan_id; - sigev.span_id = ftdmchan->span_id; - sigev.channel = ftdmchan; - /* bring the sig status down */ - sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; - sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_DOWN; - ftdm_span_send_signal(ftdmchan->span, &sigev); + sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_DOWN); /* unlock the channel again before we exit */ ftdm_mutex_unlock(ftdmchan->mutex); @@ -2050,11 +2256,25 @@ ftdm_status_t handle_cgu_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ memset(&sigev, 0, sizeof (sigev)); memset(&status[0], '\0', sizeof(status)); - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + /* confirm that the circuit is voice channel */ + if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != VOICE) { + SS7_ERROR("[CIC:%d]Rx %s on non-voice CIC\n", + g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, + DECODE_LCC_EVENT(evntType)); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); return FTDM_FAIL; + } else { + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for ISUP circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + SS7_INFO_CHAN(ftdmchan, "[CIC:%d]Rx %s\n", + g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, + DECODE_LCC_EVENT(evntType)); } /* grab the span info */ @@ -2113,11 +2333,11 @@ ftdm_status_t handle_cgu_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ switch (blockType) { /**********************************************************************/ case 0: /* maintenance oriented */ - sngss7_clear_ckt_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX); + sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX); break; /**********************************************************************/ case 1: /* hardware failure oriented */ - sngss7_clear_ckt_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX); + sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX); break; /**********************************************************************/ case 2: /* reserved for national use */ @@ -2134,9 +2354,7 @@ ftdm_status_t handle_cgu_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ sigev.channel = ftdmchan; /* bring the sig status down */ - sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; - sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_UP; - ftdm_span_send_signal(ftdmchan->span, &sigev); + sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_UP); /* unlock the channel again before we exit */ ftdm_mutex_unlock(ftdmchan->mutex); @@ -2170,11 +2388,25 @@ ftdm_status_t handle_olm_msg(uint32_t suInstId, uint32_t spInstId, uint32_t circ sngss7_chan_data_t *sngss7_info = NULL; ftdm_channel_t *ftdmchan = NULL; - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + /* confirm that the circuit is voice channel */ + if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != VOICE) { + SS7_ERROR("[CIC:%d]Rx %s on non-voice CIC\n", + g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, + DECODE_LCC_EVENT(evntType)); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); return FTDM_FAIL; + } else { + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for ISUP circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + SS7_INFO_CHAN(ftdmchan, "[CIC:%d]Rx %s\n", + g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, + DECODE_LCC_EVENT(evntType)); } /* handle overload */ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_logger.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_logger.c index f4143fc864..2a395c9ad1 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_logger.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_logger.c @@ -766,7 +766,18 @@ void handle_sng_relay_alarm(Pst *pst, RyMngmt *sta) DECODE_LRY_REASON(sta->t.usta.s.ryErrUsta.reason)); /* process the event */ - handle_relay_disconnect_on_error(sta); + switch (sta->t.usta.s.ryErrUsta.reason) { + /**********************************************************************/ + case (LRYRSNMGMTREQ): + /* do nothing since this is a shutdown */ + break; + /**********************************************************************/ + default: + /* handle the error */ + handle_relay_disconnect_on_error(sta); + break; + /**********************************************************************/ + } /* switch (sta->t.usta.s.ryErrUsta.reason) */ break; /**************************************************************************/ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c index 48579ada85..7b885102b9 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c @@ -365,6 +365,9 @@ static void *ftdm_sangoma_ss7_run(ftdm_thread_t * me, void *obj) /* check each channel on the span to see if there is an un-procressed SUS/RES flag */ check_for_res_sus_flag(ftdmspan); + /* check each channel on the span to see if it needs to be reconfigured */ + check_for_reconfig_flag(ftdmspan); + /* Poll for events, e.g HW DTMF */ switch (ftdm_span_poll_event(ftdmspan, 0, NULL)) { /**********************************************************************/ @@ -492,21 +495,17 @@ static void ftdm_sangoma_ss7_process_stack_event (sngss7_event_data_t *sngss7_ev ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) { sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; - sng_isup_inf_t *isup_intf = NULL; + sng_isup_inf_t *isup_intf = NULL; + int state_flag = 1; int i = 0; - ftdm_sigmsg_t sigev; - - memset (&sigev, 0, sizeof (sigev)); - - sigev.chan_id = ftdmchan->chan_id; - sigev.span_id = ftdmchan->span_id; - sigev.channel = ftdmchan; SS7_DEBUG_CHAN(ftdmchan, "ftmod_sangoma_ss7 processing state %s\n", ftdm_channel_state2str (ftdmchan->state)); +#if 0 /* clear the state change flag...since we might be setting a new state */ ftdm_channel_complete_state(ftdmchan); - +#endif + /*check what state we are supposed to be in */ switch (ftdmchan->state) { /**************************************************************************/ @@ -529,13 +528,15 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) ftdmchan->caller_data.dnis.digits[i-1] = '\0'; /*now go to the RING state */ - ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_RING); + state_flag = 0; + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING); } else if (i >= sngss7_info->circuit->min_digits) { SS7_DEBUG_CHAN(ftdmchan, "Received %d digits (min digits = %d)\n", i, sngss7_info->circuit->min_digits); /*now go to the RING state */ - ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_RING); + state_flag = 0; + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING); } else { /* if we are coming from idle state then we have already been here once before */ @@ -561,7 +562,8 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) sngss7_set_ckt_flag (sngss7_info, FLAG_LOCAL_REL); /* end the call */ - ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_CANCEL); + state_flag = 0; + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_CANCEL); } /* if (ftdm_sched_timer(sngss7_info->t35.sched, */ } /* if (ftdmchan->last_state != FTDM_CHANNEL_STATE_IDLE) */ } /* checking ST/#digits */ @@ -587,8 +589,7 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) /* we have enough information to inform FTDM of the call */ - sigev.event_id = FTDM_SIGEVENT_START; - ftdm_span_send_signal (ftdmchan->span, &sigev); + sngss7_send_signal(sngss7_info, FTDM_SIGEVENT_START); break; /**************************************************************************/ @@ -618,11 +619,11 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) /*check if the channel is inbound or outbound */ if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_OUTBOUND)) { /*OUTBOUND...so we were told by the line of this so noifiy the user */ - sigev.event_id = FTDM_SIGEVENT_PROGRESS; - ftdm_span_send_signal (ftdmchan->span, &sigev); + sngss7_send_signal(sngss7_info, FTDM_SIGEVENT_PROGRESS); /* move to progress media */ - ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA); + state_flag = 0; + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA); } else { /* inbound call so we need to send out ACM */ ft_to_sngss7_acm(ftdmchan); @@ -639,8 +640,7 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_OUTBOUND)) { /* inform the user there is media avai */ - sigev.event_id = FTDM_SIGEVENT_PROGRESS_MEDIA; - ftdm_span_send_signal (ftdmchan->span, &sigev); + sngss7_send_signal(sngss7_info, FTDM_SIGEVENT_PROGRESS_MEDIA); } @@ -657,8 +657,7 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) /*check if the channel is inbound or outbound */ if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_OUTBOUND)) { /*OUTBOUND...so we were told by the line that the other side answered */ - sigev.event_id = FTDM_SIGEVENT_UP; - ftdm_span_send_signal(ftdmchan->span, &sigev); + sngss7_send_signal(sngss7_info, FTDM_SIGEVENT_UP); } else { /*INBOUND...so FS told us it was going to answer...tell the stack */ ft_to_sngss7_anm(ftdmchan); @@ -676,7 +675,8 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) SS7_ERROR_CHAN(ftdmchan,"Hanging up call before informing user%s\n", " "); /*now go to the HANGUP complete state */ - ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_HANGUP); + state_flag = 0; + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); break; /**************************************************************************/ @@ -691,8 +691,7 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) sngss7_set_ckt_flag (sngss7_info, FLAG_REMOTE_REL); /*this state is set when the line is hanging up */ - sigev.event_id = FTDM_SIGEVENT_STOP; - ftdm_span_send_signal (ftdmchan->span, &sigev); + sngss7_send_signal(sngss7_info, FTDM_SIGEVENT_STOP); break; /**************************************************************************/ @@ -721,7 +720,8 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) } /*now go to the HANGUP complete state */ - ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE); + state_flag = 0; + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE); break; @@ -737,7 +737,8 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) /* check if this hangup is from a tx RSC */ if (sngss7_test_ckt_flag (sngss7_info, FLAG_RESET_TX)) { /* go to RESTART State until RSCa is received */ - ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_RESTART); + state_flag = 0; + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART); } else { /* if the hangup is from a rx RSC, rx GRS, or glare don't sent RLC */ if (!(sngss7_test_ckt_flag(sngss7_info, FLAG_RESET_RX)) && @@ -749,7 +750,8 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) } /*now go to the DOWN state */ - ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_DOWN); + state_flag = 0; + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); } SS7_DEBUG_CHAN(ftdmchan,"Completing remotely requested hangup!%s\n", ""); @@ -758,15 +760,16 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) /* if this hang up is do to a rx RESET we need to sit here till the RSP arrives */ if (sngss7_test_ckt_flag (sngss7_info, FLAG_RESET_TX_RSP)) { /* go to the down state as we have already received RSC-RLC */ - ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_DOWN); + state_flag = 0; + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); } /* if it's a local release the user sends us to down */ SS7_DEBUG_CHAN(ftdmchan,"Completing locally requested hangup!%s\n", ""); } else if (sngss7_test_ckt_flag (sngss7_info, FLAG_GLARE)) { SS7_DEBUG_CHAN(ftdmchan,"Completing requested hangup due to glare!%s\n", ""); - - ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_DOWN); + state_flag = 0; + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); } else { SS7_DEBUG_CHAN(ftdmchan,"Completing requested hangup for unknown reason!%s\n", ""); } @@ -836,28 +839,27 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) !(sngss7_test_ckt_flag (sngss7_info, FLAG_GRP_RESET_RX))) { /* now check if there is an active block */ - if (!(sngss7_test_ckt_flag(sngss7_info, FLAG_CKT_LC_BLOCK_RX)) && - !(sngss7_test_ckt_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) && - !(sngss7_test_ckt_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX)) && - !(sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX)) && - !(sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_HW_BLOCK_TX)) && - !(sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX)) && - !(sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_MN_BLOCK_TX))) { + if (!(sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_LC_BLOCK_RX)) && + !(sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) && + !(sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX)) && + !(sngss7_test_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX)) && + !(sngss7_test_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_TX)) && + !(sngss7_test_ckt_blk_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX)) && + !(sngss7_test_ckt_blk_flag(sngss7_info, FLAG_GRP_MN_BLOCK_TX))) { /* check if the sig status is down, and bring it up if it isn't */ if (!ftdm_test_flag (ftdmchan, FTDM_CHANNEL_SIG_UP)) { SS7_DEBUG_CHAN(ftdmchan,"All reset flags cleared %s\n", ""); /* all flags are down so we can bring up the sig status */ - sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; - sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_UP; - ftdm_span_send_signal (ftdmchan->span, &sigev); + sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_UP); } /* if (!ftdm_test_flag (ftdmchan, FTDM_CHANNEL_SIG_UP)) */ } /* if !blocked */ } else { SS7_DEBUG_CHAN(ftdmchan,"Reset flags present (0x%X)\n", sngss7_info->ckt_flags); /* there is still another reset pending so go back to reset*/ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); + state_flag = 0; + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART); } } /* if ((ftdmchan->last_state == FTDM_CHANNEL_STATE_RESTART) */ @@ -906,59 +908,52 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) /**************************************************************************/ case FTDM_CHANNEL_STATE_RESTART: /* CICs needs a Reset */ - if (sngss7_test_ckt_flag(sngss7_info, FLAG_CKT_UCIC_BLOCK)) { - if ((sngss7_test_ckt_flag(sngss7_info, FLAG_RESET_RX)) || - (sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX))) { + if (sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_UCIC_BLOCK)) { + if ((sngss7_test_ckt_blk_flag(sngss7_info, FLAG_RESET_RX)) || + (sngss7_test_ckt_blk_flag(sngss7_info, FLAG_GRP_RESET_RX))) { SS7_DEBUG_CHAN(ftdmchan,"Incoming Reset request on CIC in UCIC block, removing UCIC block%s\n", ""); /* set the unblk flag */ - sngss7_set_ckt_flag(sngss7_info, FLAG_CKT_UCIC_UNBLK); + sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_UCIC_UNBLK); /* clear the block flag */ - sngss7_clear_ckt_flag(sngss7_info, FLAG_CKT_UCIC_BLOCK); + sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_UCIC_BLOCK); /* process the flag */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); + state_flag = 0; + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); /* break out of the processing for now */ break; } } - /* if we're not coming from HANGUP_COMPLETE we need to check for resets - * we can also check if we are in a PAUSED state (no point in sending message - */ - if ((ftdmchan->last_state != FTDM_CHANNEL_STATE_HANGUP_COMPLETE) && - (!sngss7_test_ckt_flag(sngss7_info, FLAG_INFID_PAUSED))) { - /* check if this is an outgoing RSC */ - if ((sngss7_test_ckt_flag(sngss7_info, FLAG_RESET_TX)) && - !(sngss7_test_ckt_flag(sngss7_info, FLAG_RESET_SENT))) { + /* check if this is an outgoing RSC */ + if ((sngss7_test_ckt_flag(sngss7_info, FLAG_RESET_TX)) && + !(sngss7_test_ckt_flag(sngss7_info, FLAG_RESET_SENT))) { - /* send a reset request */ - ft_to_sngss7_rsc (ftdmchan); - sngss7_set_ckt_flag(sngss7_info, FLAG_RESET_SENT); + /* send a reset request */ + ft_to_sngss7_rsc (ftdmchan); + sngss7_set_ckt_flag(sngss7_info, FLAG_RESET_SENT); - } /* if (sngss7_test_ckt_flag(sngss7_info, FLAG_RESET_TX)) */ - - /* check if this is the first channel of a GRS (this flag is thrown when requesting reset) */ - if ( (sngss7_test_ckt_flag (sngss7_info, FLAG_GRP_RESET_TX)) && - !(sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_SENT)) && - (sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_BASE))) { + } /* if (sngss7_test_ckt_flag(sngss7_info, FLAG_RESET_TX)) */ - /* send out the grs */ - ft_to_sngss7_grs (ftdmchan); - sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_SENT); + /* check if this is the first channel of a GRS (this flag is thrown when requesting reset) */ + if ( (sngss7_test_ckt_flag (sngss7_info, FLAG_GRP_RESET_TX)) && + !(sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_SENT)) && + (sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_BASE))) { - }/* if ( sngss7_test_ckt_flag ( sngss7_info, FLAG_GRP_RESET_TX ) ) */ - } /* if ( last_state != HANGUP && !PAUSED */ + /* send out the grs */ + ft_to_sngss7_grs (ftdmchan); + sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_SENT); + + }/* if ( sngss7_test_ckt_flag ( sngss7_info, FLAG_GRP_RESET_TX ) ) */ /* if the sig_status is up...bring it down */ if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_SIG_UP)) { - sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; - sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_DOWN; - ftdm_span_send_signal (ftdmchan->span, &sigev); + sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_DOWN); } if (sngss7_test_ckt_flag (sngss7_info, FLAG_GRP_RESET_RX)) { @@ -972,13 +967,15 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) switch (ftdmchan->last_state){ /******************************************************************/ case (FTDM_CHANNEL_STATE_TERMINATING): - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); + state_flag = 0; + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); break; /******************************************************************/ case (FTDM_CHANNEL_STATE_HANGUP): case (FTDM_CHANNEL_STATE_HANGUP_COMPLETE): /* go back to the last state after taking care of the rest of the restart state */ - ftdm_set_state_locked (ftdmchan, ftdmchan->last_state); + state_flag = 0; + ftdm_set_state(ftdmchan, ftdmchan->last_state); break; /******************************************************************/ case (FTDM_CHANNEL_STATE_IN_LOOP): @@ -986,7 +983,8 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_LOOP, NULL); /* go to down */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); + state_flag = 0; + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); break; /******************************************************************/ default: @@ -996,7 +994,8 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) /* change the state to terminatting, it will throw us back here * once the call is done */ - ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); + state_flag = 0; + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); break; /******************************************************************/ } /* switch (ftdmchan->last_state) */ @@ -1010,7 +1009,8 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) SS7_DEBUG_CHAN(ftdmchan, "Reset processed moving to DOWN (0x%X)\n", sngss7_info->ckt_flags); /* go to a down state to clear the channel and send the response */ - ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_DOWN); + state_flag = 0; + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); } else { SS7_DEBUG_CHAN(ftdmchan, "Waiting on Reset Rsp/Grp Reset to move to DOWN (0x%X)\n", sngss7_info->ckt_flags); } @@ -1029,6 +1029,9 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) /* clear the RESUME flag */ sngss7_clear_ckt_flag(sngss7_info, FLAG_INFID_RESUME); + /* clear the PAUSE flag */ + sngss7_clear_ckt_flag(sngss7_info, FLAG_INFID_PAUSED); + /* if there are any resets present */ if ((sngss7_test_ckt_flag (sngss7_info, FLAG_RESET_TX)) || (sngss7_test_ckt_flag (sngss7_info, FLAG_RESET_RX)) || @@ -1040,9 +1043,7 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) } else { /* bring the sig status back up */ - sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; - sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_UP; - ftdm_span_send_signal(ftdmchan->span, &sigev); + sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_UP); } /* go back to the last state */ @@ -1053,112 +1054,125 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) SS7_DEBUG_CHAN(ftdmchan, "Processing PAUSE%s\n", ""); /* bring the sig status down */ - sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; - sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_DOWN; - ftdm_span_send_signal(ftdmchan->span, &sigev); + sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_DOWN); /* go back to the last state */ goto suspend_goto_last; } /* if (sngss7_test_ckt_flag(sngss7_info, FLAG_INFID_PAUSED)) { */ /**********************************************************************/ - if (sngss7_test_ckt_flag (sngss7_info, FLAG_CKT_MN_BLOCK_RX)) { + if (sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX) && + !sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX_DN)) { SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_MN_BLOCK_RX flag %s\n", ""); /* bring the sig status down */ - sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; - sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_DOWN; - ftdm_span_send_signal(ftdmchan->span, &sigev); + sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_DOWN); /* send a BLA */ ft_to_sngss7_bla (ftdmchan); + /* throw the done flag */ + sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX_DN); + /* check the last state and return to it to allow the call to finish */ goto suspend_goto_last; } - if (sngss7_test_ckt_flag (sngss7_info, FLAG_CKT_MN_UNBLK_RX)){ + if (sngss7_test_ckt_blk_flag (sngss7_info, FLAG_CKT_MN_UNBLK_RX) && + !sngss7_test_ckt_blk_flag (sngss7_info, FLAG_CKT_MN_UNBLK_RX_DN)){ SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_MN_UNBLK_RX flag %s\n", ""); /* clear the unblock flag */ - sngss7_clear_ckt_flag (sngss7_info, FLAG_CKT_MN_UNBLK_RX); + sngss7_clear_ckt_blk_flag (sngss7_info, FLAG_CKT_MN_UNBLK_RX); /* bring the sig status up */ - sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; - sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_UP; - ftdm_span_send_signal(ftdmchan->span, &sigev); + sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_UP); /* send a uba */ ft_to_sngss7_uba (ftdmchan); + /* throw the done flag */ + sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_UNBLK_RX_DN); + /* check the last state and return to it to allow the call to finish */ goto suspend_goto_last; } /**********************************************************************/ - if (sngss7_test_ckt_flag (sngss7_info, FLAG_CKT_MN_BLOCK_TX)) { + if (sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX) && + !sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX_DN)) { SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_MN_BLOCK_TX flag %s\n", ""); /* bring the sig status down */ - sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; - sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_DOWN; - ftdm_span_send_signal(ftdmchan->span, &sigev); + sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_DOWN); /* send a blo */ ft_to_sngss7_blo (ftdmchan); + /* throw the done flag */ + sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX_DN); + /* check the last state and return to it to allow the call to finish */ goto suspend_goto_last; } - if (sngss7_test_ckt_flag (sngss7_info, FLAG_CKT_MN_UNBLK_TX)){ + if (sngss7_test_ckt_blk_flag (sngss7_info, FLAG_CKT_MN_UNBLK_TX) && + !sngss7_test_ckt_blk_flag (sngss7_info, FLAG_CKT_MN_UNBLK_TX_DN)){ SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_MN_UNBLK_TX flag %s\n", ""); /* clear the unblock flag */ - sngss7_clear_ckt_flag (sngss7_info, FLAG_CKT_MN_UNBLK_TX); + sngss7_clear_ckt_blk_flag (sngss7_info, FLAG_CKT_MN_UNBLK_TX); /* bring the sig status up */ - sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; - sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_UP; - ftdm_span_send_signal(ftdmchan->span, &sigev); + sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_UP); /* send a ubl */ ft_to_sngss7_ubl (ftdmchan); + /* throw the done flag */ + sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_UNBLK_TX_DN); + /* check the last state and return to it to allow the call to finish */ goto suspend_goto_last; } /**********************************************************************/ - if (sngss7_test_ckt_flag (sngss7_info, FLAG_CKT_LC_BLOCK_RX)) { + if (sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_LC_BLOCK_RX) && + !sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_LC_BLOCK_RX_DN)) { SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_LC_BLOCK_RX flag %s\n", ""); /* send a BLA */ /*ft_to_sngss7_bla(ftdmchan);*/ + /* throw the done flag */ + sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_LC_BLOCK_RX_DN); + /* check the last state and return to it to allow the call to finish */ goto suspend_goto_last; } - if (sngss7_test_ckt_flag (sngss7_info, FLAG_CKT_LC_UNBLK_RX)) { + if (sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_LC_UNBLK_RX) && + !sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_LC_UNBLK_RX_DN)) { SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_LC_UNBLK_RX flag %s\n", ""); /* clear the unblock flag */ - sngss7_clear_ckt_flag (sngss7_info, FLAG_CKT_MN_UNBLK_RX); + sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_UNBLK_RX); /* send a uba */ /*ft_to_sngss7_uba(ftdmchan);*/ + /* throw the done flag */ + sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_LC_UNBLK_RX_DN); + /* check the last state and return to it to allow the call to finish */ goto suspend_goto_last; } /**********************************************************************/ - if (sngss7_test_ckt_flag (sngss7_info, FLAG_CKT_UCIC_BLOCK)) { + if (sngss7_test_ckt_blk_flag (sngss7_info, FLAG_CKT_UCIC_BLOCK) && + !sngss7_test_ckt_blk_flag (sngss7_info, FLAG_CKT_UCIC_BLOCK_DN)) { SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_UCIC_BLOCK flag %s\n", ""); /* bring the channel signaling status to down */ - sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; - sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_DOWN; - ftdm_span_send_signal (ftdmchan->span, &sigev); + sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_DOWN); /* remove any reset flags */ clear_rx_grs_flags(sngss7_info); @@ -1167,33 +1181,42 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) clear_tx_grs_data(sngss7_info); clear_rx_rsc_flags(sngss7_info); clear_tx_rsc_flags(sngss7_info); + + /* throw the done flag */ + sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_UCIC_BLOCK_DN); /* bring the channel down */ goto suspend_goto_last; } - if (sngss7_test_ckt_flag (sngss7_info, FLAG_CKT_UCIC_UNBLK)) { + if (sngss7_test_ckt_blk_flag (sngss7_info, FLAG_CKT_UCIC_UNBLK) && + !sngss7_test_ckt_blk_flag (sngss7_info, FLAG_CKT_UCIC_UNBLK_DN)) { SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_UCIC_UNBLK flag %s\n", "");; /* remove the UCIC block flag */ - sngss7_clear_ckt_flag(sngss7_info, FLAG_CKT_UCIC_BLOCK); + sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_UCIC_BLOCK); /* remove the UCIC unblock flag */ - sngss7_clear_ckt_flag(sngss7_info, FLAG_CKT_UCIC_UNBLK); + sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_UCIC_UNBLK); /* throw the channel into reset to sync states */ sngss7_set_ckt_flag(sngss7_info, FLAG_RESET_TX); + /* throw the done flag */ + sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_UCIC_UNBLK_DN); + /* bring the channel into restart again */ goto suspend_goto_restart; } suspend_goto_last: - ftdm_set_state_locked (ftdmchan, ftdmchan->last_state); + state_flag = 0; + ftdm_set_state(ftdmchan, ftdmchan->last_state); break; suspend_goto_restart: - ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_RESTART); + state_flag = 0; + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART); break; /**************************************************************************/ @@ -1209,7 +1232,8 @@ suspend_goto_restart: break; /**************************************************************************/ case FTDM_CHANNEL_STATE_IDLE: - ftdm_set_state_locked(ftdmchan, ftdmchan->last_state); + state_flag = 0; + ftdm_set_state(ftdmchan, ftdmchan->last_state); break; /**************************************************************************/ default: @@ -1219,7 +1243,12 @@ suspend_goto_restart: break; /**************************************************************************/ }/*switch (ftdmchan->state) */ - +#if 1 + if (state_flag) { + /* clear the state change flag...since we might be setting a new state */ + ftdm_channel_complete_state(ftdmchan); + } +#endif return FTDM_SUCCESS; } @@ -1228,17 +1257,7 @@ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(ftdm_sangoma_ss7_outgoing_call) { sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; - /* lock the channel while we check whether it is availble */ - ftdm_mutex_lock (ftdmchan->mutex); - - /* check if there is a pending state change, give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); - /* check if we need to die */ - SS7_ASSERT; - /* end the request */ - goto outgoing_fail; - }; + /* the core has this channel already locked so need to lock again */ /* check if the channel sig state is UP */ if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) { @@ -1247,9 +1266,9 @@ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(ftdm_sangoma_ss7_outgoing_call) } /* check if there is a remote block */ - if ((sngss7_test_ckt_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) || - (sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX)) || - (sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX))) { + if ((sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) || + (sngss7_test_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX)) || + (sngss7_test_ckt_blk_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX))) { /* the channel is blocked...can't send any calls here */ SS7_ERROR_CHAN(ftdmchan, "Requested channel is remotely blocked, re-hunt channel!%s\n", " "); @@ -1257,9 +1276,9 @@ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(ftdm_sangoma_ss7_outgoing_call) } /* check if there is a local block */ - if ((sngss7_test_ckt_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX)) || - (sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_HW_BLOCK_TX)) || - (sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_MN_BLOCK_TX))) { + if ((sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX)) || + (sngss7_test_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_TX)) || + (sngss7_test_ckt_blk_flag(sngss7_info, FLAG_GRP_MN_BLOCK_TX))) { /* KONRAD FIX ME : we should check if this is a TEST call and allow it */ @@ -1272,11 +1291,7 @@ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(ftdm_sangoma_ss7_outgoing_call) switch (ftdmchan->state){ /**************************************************************************/ case FTDM_CHANNEL_STATE_DOWN: - /* inform the monitor thread that we want to make a call */ - ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_DIALING); - - /* unlock the channel */ - ftdm_mutex_unlock (ftdmchan->mutex); + /* inform the monitor thread that we want to make a call by returning FTDM_SUCCESS */ goto outgoing_successful; break; @@ -1294,20 +1309,14 @@ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(ftdm_sangoma_ss7_outgoing_call) outgoing_fail: SS7_DEBUG_CHAN(ftdmchan, "Call Request failed%s\n", " "); - /* unlock the channel */ - ftdm_mutex_unlock (ftdmchan->mutex); return FTDM_FAIL; outgoing_break: SS7_DEBUG_CHAN(ftdmchan, "Call Request re-hunt%s\n", " "); - /* unlock the channel */ - ftdm_mutex_unlock (ftdmchan->mutex); return FTDM_BREAK; outgoing_successful: SS7_DEBUG_CHAN(ftdmchan, "Call Request successful%s\n", " "); - /* unlock the channel */ - ftdm_mutex_unlock (ftdmchan->mutex); return FTDM_SUCCESS; } @@ -1385,6 +1394,9 @@ static ftdm_status_t ftdm_sangoma_ss7_start(ftdm_span_t * span) /* lock the channel */ ftdm_mutex_lock(ftdmchan->mutex); + /* flag the circuit as active */ + sngss7_set_flag(sngss7_info->circuit, SNGSS7_ACTIVE); + /* check if the interface is paused or resumed */ if (sngss7_test_flag(sngss7_intf, SNGSS7_PAUSED)) { SS7_DEBUG_CHAN(ftdmchan, "ISUP intf %d is PAUSED\n", sngss7_intf->id); @@ -1410,7 +1422,7 @@ static ftdm_status_t ftdm_sangoma_ss7_start(ftdm_span_t * span) sngss7_set_ckt_flag(sngss7_info, FLAG_RESET_TX); #endif /* throw the channel to suspend */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); /* unlock the channel */ ftdm_mutex_unlock(ftdmchan->mutex); @@ -1583,6 +1595,8 @@ static FIO_SIG_UNLOAD_FUNCTION(ftdm_sangoma_ss7_unload) { /*this function is called by the FT-core to unload the signaling module */ + int x; + ftdm_log (FTDM_LOG_INFO, "Starting ftmod_sangoma_ss7 unload...\n"); if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_CC)) { @@ -1610,6 +1624,26 @@ static FIO_SIG_UNLOAD_FUNCTION(ftdm_sangoma_ss7_unload) } if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_RY)) { + /* go through all the relays channels and configure it */ + x = 1; + while (g_ftdm_sngss7_data.cfg.relay[x].id != 0) { + /* check if this relay channel has been configured already */ + if ((g_ftdm_sngss7_data.cfg.relay[x].flags & SNGSS7_CONFIGURED)) { + + /* send the specific configuration */ + if (ftmod_ss7_disable_relay_channel(x)) { + SS7_CRITICAL("Relay Channel %d disable failed!\n", x); + return 1; + } else { + SS7_INFO("Relay Channel %d disable DONE!\n", x); + } + + /* set the SNGSS7_CONFIGURED flag */ + g_ftdm_sngss7_data.cfg.relay[x].flags &= !SNGSS7_CONFIGURED; + } /* if !SNGSS7_CONFIGURED */ + x++; + } /* while (g_ftdm_sngss7_data.cfg.relay[x].id != 0) */ + ftmod_ss7_shutdown_relay(); sng_isup_free_relay(); sngss7_clear_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_RY); diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h index 05c63518ec..02c450b94a 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h @@ -76,6 +76,17 @@ typedef enum { SNGSS7_SSP_STA_CFM_EVENT } sng_event_type_t; +typedef enum { + SNG_BIT_A = (1 << 0), + SNG_BIT_B = (1 << 1), + SNG_BIT_C = (1 << 2), + SNG_BIT_D = (1 << 3), + SNG_BIT_E = (1 << 4), + SNG_BIT_F = (1 << 5), + SNG_BIT_G = (1 << 6), + SNG_BIT_H = (1 << 7) +} sng_bit_enums_t; + typedef enum { VOICE = 0, SIG, @@ -294,7 +305,6 @@ typedef struct sng_isup_intf { typedef struct sng_isup_ckt { uint32_t options; uint32_t flags; - uint32_t ckt_flags; uint32_t procId; uint32_t id; uint32_t ccSpanId; @@ -431,6 +441,10 @@ typedef struct sngss7_chan_data { uint32_t spId; uint8_t globalFlg; uint32_t ckt_flags; + uint32_t blk_flags; + ftdm_hash_t* variables; /* send on next sigevent */ + ftdm_size_t raw_data_len; + void *raw_data; /* send on next sigevent */ sngss7_glare_data_t glare; sngss7_timer_data_t t35; }sngss7_chan_data_t; @@ -489,23 +503,63 @@ typedef enum { FLAG_GLARE = (1 << 13), FLAG_INFID_RESUME = (1 << 14), FLAG_INFID_PAUSED = (1 << 15), - FLAG_CKT_UCIC_BLOCK = (1 << 16), - FLAG_CKT_UCIC_UNBLK = (1 << 17), - FLAG_CKT_LC_BLOCK_RX = (1 << 18), - FLAG_CKT_LC_UNBLK_RX = (1 << 19), - FLAG_CKT_MN_BLOCK_RX = (1 << 20), - FLAG_CKT_MN_UNBLK_RX = (1 << 21), - FLAG_CKT_MN_BLOCK_TX = (1 << 22), - FLAG_CKT_MN_UNBLK_TX = (1 << 23), - FLAG_GRP_HW_BLOCK_RX = (1 << 24), - FLAG_GRP_HW_BLOCK_TX = (1 << 25), - FLAG_GRP_MN_BLOCK_RX = (1 << 26), - FLAG_GRP_MN_BLOCK_TX = (1 << 27), - FLAG_GRP_HW_UNBLK_TX = (1 << 28), - FLAG_GRP_MN_UNBLK_TX = (1 << 29), - FLAG_RELAY_DOWN = (1 << 30) + FLAG_RELAY_DOWN = (1 << 30), + FLAG_CKT_RECONFIG = (1 << 31) } sng_ckt_flag_t; +#define CKT_FLAGS_STRING \ + "RX_RSC", \ + "TX_RSC", \ + "TX_RSC_REQ_SENT", \ + "TX_RSC_RSP_RECIEVED", \ + "RX_GRS", \ + "RX_GRS_DONE", \ + "RX_GRS_CMPLT", \ + "GRS_BASE", \ + "TX_GRS", \ + "TX_GRS_REQ_SENT", \ + "TX_GRS_RSP_RECIEVED", \ + "REMOTE_REL", \ + "LOCAL_REL", \ + "GLARE", \ + "INF_RESUME", \ + "INF_PAUSED", \ + "RELAY_DOWN", \ + "CKT_RECONFIG" +FTDM_STR2ENUM_P(ftmod_ss7_ckt_state2flag, ftmod_ss7_ckt_flag2str, sng_ckt_flag_t) + +/* ckt blocking flags */ +typedef enum { + FLAG_CKT_UCIC_BLOCK = (1 << 0), + FLAG_CKT_UCIC_BLOCK_DN = (1 << 1), + FLAG_CKT_UCIC_UNBLK = (1 << 2), + FLAG_CKT_UCIC_UNBLK_DN = (1 << 3), + FLAG_CKT_LC_BLOCK_RX = (1 << 4), + FLAG_CKT_LC_BLOCK_RX_DN = (1 << 5), + FLAG_CKT_LC_UNBLK_RX = (1 << 6), + FLAG_CKT_LC_UNBLK_RX_DN = (1 << 7), + FLAG_CKT_MN_BLOCK_RX = (1 << 8), + FLAG_CKT_MN_BLOCK_RX_DN = (1 << 9), + FLAG_CKT_MN_UNBLK_RX = (1 << 10), + FLAG_CKT_MN_UNBLK_RX_DN = (1 << 11), + FLAG_CKT_MN_BLOCK_TX = (1 << 12), + FLAG_CKT_MN_BLOCK_TX_DN = (1 << 13), + FLAG_CKT_MN_UNBLK_TX = (1 << 14), + FLAG_CKT_MN_UNBLK_TX_DN = (1 << 15), + FLAG_GRP_HW_BLOCK_RX = (1 << 16), + FLAG_GRP_HW_BLOCK_RX_DN = (1 << 17), + FLAG_GRP_HW_BLOCK_TX = (1 << 18), + FLAG_GRP_HW_BLOCK_TX_DN = (1 << 19), + FLAG_GRP_MN_BLOCK_RX = (1 << 20), + FLAG_GRP_MN_BLOCK_RX_DN = (1 << 21), + FLAG_GRP_MN_BLOCK_TX = (1 << 22), + FLAG_GRP_MN_BLOCK_TX_DN = (1 << 23), + FLAG_GRP_HW_UNBLK_TX = (1 << 24), + FLAG_GRP_HW_UNBLK_TX_DN = (1 << 25), + FLAG_GRP_MN_UNBLK_TX = (1 << 26), + FLAG_GRP_MN_UNBLK_TX_DN = (1 << 27) +} sng_ckt_block_flag_t; + /* valid for every cfg array except circuits */ typedef enum { SNGSS7_CONFIGURED = (1 << 0), @@ -594,12 +648,17 @@ int ftmod_ss7_shutdown_isup(void); int ftmod_ss7_shutdown_mtp3(void); int ftmod_ss7_shutdown_mtp2(void); int ftmod_ss7_shutdown_relay(void); +int ftmod_ss7_disable_relay_channel(uint32_t chanId); int ftmod_ss7_disable_grp_mtp3Link(uint32_t procId); int ftmod_ss7_enable_grp_mtp3Link(uint32_t procId); int ftmod_ss7_disable_grp_mtp2Link(uint32_t procId); +int ftmod_ss7_block_isup_ckt(uint32_t cktId); + + + /* in ftmod_sangoma_ss7_sta.c */ int ftmod_ss7_mtp1link_sta(uint32_t id, L1Mngmt *cfm); int ftmod_ss7_mtp2link_sta(uint32_t id, SdMngmt *cfm); @@ -607,6 +666,7 @@ int ftmod_ss7_mtp3link_sta(uint32_t id, SnMngmt *cfm); int ftmod_ss7_mtplinkSet_sta(uint32_t id, SnMngmt *cfm); int ftmod_ss7_isup_intf_sta(uint32_t id, uint8_t *status); int ftmod_ss7_relay_status(uint32_t id, RyMngmt *cfm); +int ftmod_ss7_isup_ckt_sta(uint32_t id, unsigned char *state); /* in ftmod_sangoma_ss7_out.c */ @@ -723,6 +783,12 @@ int find_ssf_type_in_map(const char *ssfType); int find_cic_cntrl_in_map(const char *cntrlType); ftdm_status_t check_status_of_all_isup_intf(void); +ftdm_status_t check_for_reconfig_flag(ftdm_span_t *ftdmspan); + +void sngss7_send_signal(sngss7_chan_data_t *sngss7_info, ftdm_signal_event_t event_id); +void sngss7_set_sig_status(sngss7_chan_data_t *sngss7_info, ftdm_signaling_status_t status); +ftdm_status_t sngss7_add_var(sngss7_chan_data_t *ss7_info, const char* var, const char* val); +ftdm_status_t sngss7_add_raw_data(sngss7_chan_data_t *sngss7_info, uint8_t* data, ftdm_size_t data_len); /* in ftmod_sangoma_ss7_timers.c */ void handle_isup_t35(void *userdata); @@ -860,6 +926,10 @@ void handle_isup_t35(void *userdata); #define sngss7_clear_ckt_flag(obj, flag) ((obj)->ckt_flags &= ~(flag)) #define sngss7_set_ckt_flag(obj, flag) ((obj)->ckt_flags |= (flag)) +#define sngss7_test_ckt_blk_flag(obj, flag) ((obj)->blk_flags & flag) +#define sngss7_clear_ckt_blk_flag(obj, flag) ((obj)->blk_flags &= ~(flag)) +#define sngss7_set_ckt_blk_flag(obj, flag) ((obj)->blk_flags |= (flag)) + #define sngss7_test_options(obj, option) ((obj)->options & option) #define sngss7_clear_options(obj, option) ((obj)->options &= ~(option)) #define sngss7_set_options(obj, option) ((obj)->options |= (option)) diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c index 918b284de1..96446b4215 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c @@ -187,7 +187,7 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan) copy_cgPtyNum_to_sngss7 (&ftdmchan->caller_data, &iam.cgPtyNum); /* check if the user would like a custom NADI value for the calling Pty Num */ - clg_nadi = ftdm_call_get_var(&ftdmchan->caller_data, "ss7_clg_nadi"); + clg_nadi = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_clg_nadi"); if ((clg_nadi != NULL) && (*clg_nadi)) { SS7_DEBUG_CHAN(ftdmchan,"Found user supplied Calling NADI value \"%s\"\n", clg_nadi); iam.cgPtyNum.natAddrInd.val = atoi(clg_nadi); @@ -196,7 +196,7 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan) SS7_DEBUG_CHAN(ftdmchan,"No user supplied NADI value found for CLG, using \"%d\"\n", iam.cgPtyNum.natAddrInd.val); } - cld_nadi = ftdm_call_get_var(&ftdmchan->caller_data, "ss7_cld_nadi"); + cld_nadi = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_cld_nadi"); if ((cld_nadi != NULL) && (*cld_nadi)) { SS7_DEBUG_CHAN(ftdmchan,"Found user supplied Called NADI value \"%s\"\n", cld_nadi); iam.cdPtyNum.natAddrInd.val = atoi(cld_nadi); @@ -206,7 +206,7 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan) } /* check if the user would like us to send a clg_sub-address */ - clg_subAddr = ftdm_call_get_var(&ftdmchan->caller_data, "ss7_clg_subaddr"); + clg_subAddr = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_clg_subaddr"); if ((clg_subAddr != NULL) && (*clg_subAddr)) { SS7_DEBUG_CHAN(ftdmchan,"Found user supplied Calling Sub-Address value \"%s\"\n", clg_subAddr); @@ -245,7 +245,7 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan) } /* check if the user would like us to send a cld_sub-address */ - cld_subAddr = ftdm_call_get_var(&ftdmchan->caller_data, "ss7_cld_subaddr"); + cld_subAddr = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_cld_subaddr"); if ((cld_subAddr != NULL) && (*cld_subAddr)) { SS7_DEBUG_CHAN(ftdmchan,"Found user supplied Called Sub-Address value \"%s\"\n", cld_subAddr); @@ -282,9 +282,6 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan) } /* if (subAddrIE[0] != '0') */ } /* if ((cld_subAddr != NULL) && (*cld_subAddr)) */ - - - sng_cc_con_request (sngss7_info->spId, sngss7_info->suInstId, sngss7_info->spInstId, @@ -299,7 +296,7 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan) ftdmchan->caller_data.dnis.digits, iam.cdPtyNum.natAddrInd.val); - ftdm_call_clear_data(&ftdmchan->caller_data); + SS7_FUNC_TRACE_EXIT (__FUNCTION__); return; } @@ -379,7 +376,7 @@ void ft_to_sngss7_acm (ftdm_channel_t * ftdmchan) ADDRCMPLT); SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx ACM\n", sngss7_info->circuit->cic); - ftdm_call_clear_data(&ftdmchan->caller_data); + SS7_FUNC_TRACE_EXIT (__FUNCTION__); return; } @@ -403,7 +400,7 @@ void ft_to_sngss7_anm (ftdm_channel_t * ftdmchan) 5); SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx ANM\n", sngss7_info->circuit->cic); - ftdm_call_clear_data(&ftdmchan->caller_data); + SS7_FUNC_TRACE_EXIT (__FUNCTION__); return; } @@ -438,7 +435,7 @@ void ft_to_sngss7_rel (ftdm_channel_t * ftdmchan) SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx REL cause=%d \n", sngss7_info->circuit->cic, ftdmchan->caller_data.hangup_cause ); - ftdm_call_clear_data(&ftdmchan->caller_data); + SS7_FUNC_TRACE_EXIT (__FUNCTION__); return; } @@ -461,7 +458,7 @@ void ft_to_sngss7_rlc (ftdm_channel_t * ftdmchan) &rlc); SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx RLC\n", sngss7_info->circuit->cic); - ftdm_call_clear_data(&ftdmchan->caller_data); + SS7_FUNC_TRACE_EXIT (__FUNCTION__); return; } @@ -482,7 +479,7 @@ void ft_to_sngss7_rsc (ftdm_channel_t * ftdmchan) NULL); SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx RSC\n", sngss7_info->circuit->cic); - ftdm_call_clear_data(&ftdmchan->caller_data); + SS7_FUNC_TRACE_EXIT (__FUNCTION__); return; } @@ -503,7 +500,7 @@ void ft_to_sngss7_rsca (ftdm_channel_t * ftdmchan) NULL); SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx RSC-RLC\n", sngss7_info->circuit->cic); - ftdm_call_clear_data(&ftdmchan->caller_data); + SS7_FUNC_TRACE_EXIT (__FUNCTION__); return; } @@ -524,7 +521,7 @@ void ft_to_sngss7_blo (ftdm_channel_t * ftdmchan) NULL); SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx BLO\n", sngss7_info->circuit->cic); - ftdm_call_clear_data(&ftdmchan->caller_data); + SS7_FUNC_TRACE_EXIT (__FUNCTION__); return; } @@ -545,7 +542,7 @@ void ft_to_sngss7_bla (ftdm_channel_t * ftdmchan) NULL); SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx BLA\n", sngss7_info->circuit->cic); - ftdm_call_clear_data(&ftdmchan->caller_data); + SS7_FUNC_TRACE_EXIT (__FUNCTION__); return; } @@ -567,7 +564,7 @@ ft_to_sngss7_ubl (ftdm_channel_t * ftdmchan) NULL); SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx UBL\n", sngss7_info->circuit->cic); - ftdm_call_clear_data(&ftdmchan->caller_data); + SS7_FUNC_TRACE_EXIT (__FUNCTION__); return; } @@ -588,7 +585,7 @@ void ft_to_sngss7_uba (ftdm_channel_t * ftdmchan) NULL); SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx UBA\n", sngss7_info->circuit->cic); - ftdm_call_clear_data(&ftdmchan->caller_data); + SS7_FUNC_TRACE_EXIT (__FUNCTION__); return; } @@ -609,7 +606,7 @@ void ft_to_sngss7_lpa (ftdm_channel_t * ftdmchan) NULL); SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx LPA\n", sngss7_info->circuit->cic); - ftdm_call_clear_data(&ftdmchan->caller_data); + SS7_FUNC_TRACE_EXIT (__FUNCTION__); return; } @@ -654,7 +651,7 @@ void ft_to_sngss7_gra (ftdm_channel_t * ftdmchan) sngss7_info->circuit->cic, (sngss7_info->circuit->cic + sngss7_span->rx_grs.range)); - ftdm_call_clear_data(&ftdmchan->caller_data); + SS7_FUNC_TRACE_EXIT (__FUNCTION__); return; } @@ -688,7 +685,7 @@ void ft_to_sngss7_grs (ftdm_channel_t * ftdmchan) sngss7_info->circuit->cic, (sngss7_info->circuit->cic + sngss7_span->tx_grs.range)); - ftdm_call_clear_data(&ftdmchan->caller_data); + SS7_FUNC_TRACE_EXIT (__FUNCTION__); return; } @@ -737,7 +734,7 @@ void ft_to_sngss7_cgba(ftdm_channel_t * ftdmchan) /* clean out the saved data */ memset(&sngss7_span->rx_cgb, 0x0, sizeof(sngss7_group_data_t)); - ftdm_call_clear_data(&ftdmchan->caller_data); + SS7_FUNC_TRACE_EXIT (__FUNCTION__); return; } @@ -787,7 +784,7 @@ void ft_to_sngss7_cgua(ftdm_channel_t * ftdmchan) /* clean out the saved data */ memset(&sngss7_span->rx_cgu, 0x0, sizeof(sngss7_group_data_t)); - ftdm_call_clear_data(&ftdmchan->caller_data); + SS7_FUNC_TRACE_EXIT (__FUNCTION__); return; } @@ -838,7 +835,7 @@ void ft_to_sngss7_cgb(ftdm_channel_t * ftdmchan) /* clean out the saved data */ memset(&sngss7_span->tx_cgb, 0x0, sizeof(sngss7_group_data_t)); - ftdm_call_clear_data(&ftdmchan->caller_data); + SS7_FUNC_TRACE_EXIT (__FUNCTION__); return; } @@ -889,7 +886,7 @@ void ft_to_sngss7_cgu(ftdm_channel_t * ftdmchan) /* clean out the saved data */ memset(&sngss7_span->tx_cgu, 0x0, sizeof(sngss7_group_data_t)); - ftdm_call_clear_data(&ftdmchan->caller_data); + SS7_FUNC_TRACE_EXIT (__FUNCTION__); return; } diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_relay.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_relay.c index 05ea69ea69..d34d62c217 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_relay.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_relay.c @@ -61,23 +61,28 @@ ftdm_status_t handle_relay_connect(RyMngmt *sta) /* test if this is the first time the channel comes up */ if (!sngss7_test_flag(sng_relay, SNGSS7_RELAY_INIT)) { - SS7_DEBUG("Relay Channel %d initial connection UP\n", sng_relay->id); + SS7_INFO("Relay Channel %d initial connection UP\n", sng_relay->id); /* mark the channel as being up */ sngss7_set_flag(sng_relay, SNGSS7_RELAY_INIT); } else { - SS7_DEBUG("Relay Channel %d connection UP\n", sng_relay->id); + SS7_INFO("Relay Channel %d connection UP\n", sng_relay->id); /* react based on type of channel */ switch (sng_relay->type) { /******************************************************************/ case (LRY_CT_TCP_CLIENT): + /* check the status of all isup intfs in case we weren't connected when + * the interface became active + */ + check_status_of_all_isup_intf(); + /* reconfigure all ISUP ckts, since the main system would have lost all configs */ if (reconfig_all_ckts_for_relay()) { SS7_ERROR("Failed to reconfigure ISUP Ckts!\n"); - /* we're done....this is very bad! */ - } else { + } else { + /* if the circuits reconfiged then bring then back up */ enable_all_ckts_for_relay(); } @@ -104,16 +109,20 @@ ftdm_status_t handle_relay_disconnect_on_error(RyMngmt *sta) /* check which procId is in error, if it is 1, disable the ckts */ if (sta->t.usta.s.ryErrUsta.errPid == 1 ) { - disable_all_ckts_for_relay(); - + /* we've lost the server, bring down the mtp2 links */ disble_all_mtp2_sigs_for_relay(); + + /* we've lost the server, bring the sig status down on all ckts */ + disable_all_ckts_for_relay(); } /* check if the channel is a server, means we just lost a MGW */ if (g_ftdm_sngss7_data.cfg.relay[sta->t.usta.s.ryErrUsta.errPid].type == LRY_CT_TCP_SERVER) { - block_all_ckts_for_relay(sta->t.usta.s.ryErrUsta.errPid); - + /* we've lost the client, bring down all mtp3 links for this procId */ disable_all_sigs_for_relay(sta->t.usta.s.ryErrUsta.errPid); + + /* we've lost the client, bring down all the ckts for this procId */ + block_all_ckts_for_relay(sta->t.usta.s.ryErrUsta.errPid); } return FTDM_SUCCESS; @@ -207,7 +216,7 @@ ftdm_status_t enable_all_ckts_for_relay(void) SS7_DEBUG_CHAN(ftdmchan, "ISUP interface (%d) set to resume, resuming channel\n", sngIntf->id); /* throw the channel infId status flags to PAUSED ... they will be executed next process cycle */ sngss7_set_ckt_flag(sngss7_info, FLAG_INFID_RESUME); - sngss7_set_ckt_flag(sngss7_info, FLAG_INFID_PAUSED); + sngss7_clear_ckt_flag(sngss7_info, FLAG_INFID_PAUSED); } } /* if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) */ @@ -222,30 +231,26 @@ ftdm_status_t enable_all_ckts_for_relay(void) /******************************************************************************/ ftdm_status_t reconfig_all_ckts_for_relay(void) { -#if 1 int x; - int ret; + sngss7_chan_data_t *sngss7_info = NULL; + /* go through all the circuits on our ProcId */ x = (g_ftdm_sngss7_data.cfg.procId * 1000) + 1; while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) { + /**************************************************************************/ if ( g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) { - - ret = ftmod_ss7_isup_ckt_config(x); - if (ret) { - SS7_CRITICAL("ISUP CKT %d configuration FAILED (%d)!\n", x, ret); - return 1; - } else { - SS7_INFO("ISUP CKT %d configuration DONE!\n", x); - } + /* grab the private data structure */ + sngss7_info = g_ftdm_sngss7_data.cfg.isupCkt[x].obj; + + /* mark the circuit for re-configuration */ + sngss7_set_ckt_flag(sngss7_info, FLAG_CKT_RECONFIG); + } - } /* if ( g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) */ - - /* set the SNGSS7_CONFIGURED flag */ - g_ftdm_sngss7_data.cfg.isupCkt[x].flags |= SNGSS7_CONFIGURED; - + /* move to the next circuit */ x++; + /**************************************************************************/ } /* while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) */ -#endif + return FTDM_SUCCESS; } @@ -253,23 +258,26 @@ ftdm_status_t reconfig_all_ckts_for_relay(void) ftdm_status_t block_all_ckts_for_relay(uint32_t procId) { int x; - - SS7_INFO("BLOcking all ckts on ProcID = %d\n", procId); + int ret; /* we just lost connection to this procId, send out a block for all these circuits */ x = (procId * 1000) + 1; while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) { /**************************************************************************/ if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) { - /* send out a BLO */ - sng_cc_sta_request (1, - 0, - 0, - g_ftdm_sngss7_data.cfg.isupCkt[x].id, - 0, - SIT_STA_CIRBLOREQ, - NULL); + /* send a block request via stack manager */ + ret = ftmod_ss7_block_isup_ckt(g_ftdm_sngss7_data.cfg.isupCkt[x].id); + if (ret) { + SS7_INFO("Successfully BLOcked CIC:%d(ckt:%d) due to Relay failure\n", + g_ftdm_sngss7_data.cfg.isupCkt[x].cic, + g_ftdm_sngss7_data.cfg.isupCkt[x].id); + } else { + SS7_ERROR("Failed to BLOck CIC:%d(ckt:%d) due to Relay failure\n", + g_ftdm_sngss7_data.cfg.isupCkt[x].cic, + g_ftdm_sngss7_data.cfg.isupCkt[x].id); + } + } /* if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) */ /* move along */ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sta.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sta.c index 2f507a2ad4..a2d8e23d5c 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sta.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sta.c @@ -48,6 +48,7 @@ int ftmod_ss7_mtp3link_sta(uint32_t id, SnMngmt *cfm); int ftmod_ss7_mtplinkSet_sta(uint32_t id, SnMngmt *cfm); int ftmod_ss7_isup_intf_sta(uint32_t id, uint8_t *status); int ftmod_ss7_relay_status(uint32_t id, RyMngmt *cfm); +int ftmod_ss7_isup_ckt_sta(uint32_t id, unsigned char *state); /******************************************************************************/ /* FUNCTIONS ******************************************************************/ @@ -188,6 +189,43 @@ int ftmod_ss7_relay_status(uint32_t id, RyMngmt *cfm) return(sng_sta_relay(&pst, &sta, cfm)); } +/******************************************************************************/ +int ftmod_ss7_isup_ckt_sta(uint32_t id, unsigned char *state) +{ + SiMngmt sta; + SiMngmt cfm; + Pst pst; + int ret; + + memset(&sta, 0x0, sizeof(sta)); + + /* initalize the post structure */ + smPstInit(&pst); + + /* insert the destination Entity */ + pst.dstEnt = ENTSI; + + /* check the for the correct ProcId and make sure it goes to the right system */ + if (g_ftdm_sngss7_data.cfg.procId != 1) { + pst.dstProcId = 1; + } + + /* request the status of an inftId */ + sta.hdr.entId.ent = ENTSI; + sta.hdr.entId.inst = S_INST; + sta.hdr.msgType = TSSTA; + sta.hdr.elmId.elmnt = SI_STCIRGRP; + + sta.t.ssta.elmntId.circuit = id; + sta.t.ssta.param.cirgr.range = 1; + + ret = sng_sta_isup(&pst, &sta, &cfm); + + *state = cfm.t.ssta.cfm.s.cir.state[0]; + + return(ret); +} + /******************************************************************************/ /* For Emacs: * Local Variables: diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c index 683caf2352..ded695c205 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c @@ -83,8 +83,17 @@ int find_ssf_type_in_map(const char *ssfType); int find_cic_cntrl_in_map(const char *cntrlType); ftdm_status_t check_status_of_all_isup_intf(void); +ftdm_status_t check_for_reconfig_flag(ftdm_span_t *ftdmspan); + +void sngss7_send_signal(sngss7_chan_data_t *sngss7_info, ftdm_signal_event_t event_id); +void sngss7_set_sig_status(sngss7_chan_data_t *sngss7_info, ftdm_signaling_status_t status); +ftdm_status_t sngss7_add_var(sngss7_chan_data_t *ss7_info, const char* var, const char* val); +ftdm_status_t sngss7_add_raw_data(sngss7_chan_data_t *sngss7_info, uint8_t* data, ftdm_size_t data_len); /******************************************************************************/ +FTDM_ENUM_NAMES(CKT_FLAGS_NAMES, CKT_FLAGS_STRING) +FTDM_STR2ENUM(ftmod_ss7_ckt_state2flag, ftmod_ss7_ckt_flag2str, sng_ckt_flag_t, CKT_FLAGS_NAMES, 31) + /* FUNCTIONS ******************************************************************/ uint8_t copy_cgPtyNum_from_sngss7(ftdm_caller_data_t *ftdm, SiCgPtyNum *cgPtyNum) { @@ -526,8 +535,18 @@ ftdm_status_t check_if_rx_grs_started(ftdm_span_t *ftdmspan) sngss7_span_data_t *sngss7_span = (sngss7_span_data_t *)ftdmspan->signal_data; int i; + + SS7_INFO("Rx GRS (%d:%d)\n", + g_ftdm_sngss7_data.cfg.isupCkt[sngss7_span->rx_grs.circuit].cic, + (g_ftdm_sngss7_data.cfg.isupCkt[sngss7_span->rx_grs.circuit].cic + sngss7_span->rx_grs.range)); + for ( i = sngss7_span->rx_grs.circuit; i < (sngss7_span->rx_grs.circuit + sngss7_span->rx_grs.range + 1); i++) { + /* confirm this is a voice channel, otherwise we do nothing */ + if (g_ftdm_sngss7_data.cfg.isupCkt[i].type != VOICE) { + continue; + } + /* extract the channel in question */ if (extract_chan_data(i, &sngss7_info, &ftdmchan)) { SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i); @@ -548,10 +567,6 @@ ftdm_status_t check_if_rx_grs_started(ftdm_span_t *ftdmspan) ftdm_sangoma_ss7_process_state_change (ftdmchan); } - SS7_INFO_CHAN(ftdmchan, "Rx GRS (%d:%d)\n", - g_ftdm_sngss7_data.cfg.isupCkt[sngss7_span->rx_grs.circuit].cic, - (g_ftdm_sngss7_data.cfg.isupCkt[sngss7_span->rx_grs.circuit].cic + sngss7_span->rx_grs.range)); - /* flag the channel as having received a reset */ sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX); @@ -560,14 +575,14 @@ ftdm_status_t check_if_rx_grs_started(ftdm_span_t *ftdmspan) case FTDM_CHANNEL_STATE_RESTART: /* go to idle so that we can redo the restart state*/ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_IDLE); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_IDLE); break; /**************************************************************************/ default: /* set the state of the channel to restart...the rest is done by the chan monitor */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART); break; /**************************************************************************/ } /* switch (ftdmchan->state) */ @@ -590,12 +605,14 @@ ftdm_status_t check_if_rx_grs_processed(ftdm_span_t *ftdmspan) int byte = 0; int bit = 0; - - ftdm_log(FTDM_LOG_DEBUG, "Found Rx GRS on span %s...checking circuits\n", ftdmspan->name); - /* check all the circuits in the range to see if they are done resetting */ for ( i = sngss7_span->rx_grs.circuit; i < (sngss7_span->rx_grs.circuit + sngss7_span->rx_grs.range + 1); i++) { + /* confirm this is a voice channel, otherwise we do nothing */ + if (g_ftdm_sngss7_data.cfg.isupCkt[i].type != VOICE) { + continue; + } + /* extract the channel in question */ if (extract_chan_data(i, &sngss7_info, &ftdmchan)) { SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i); @@ -625,6 +642,11 @@ ftdm_status_t check_if_rx_grs_processed(ftdm_span_t *ftdmspan) /* check all the circuits in the range to see if they are done resetting */ for ( i = sngss7_span->rx_grs.circuit; i < (sngss7_span->rx_grs.circuit + sngss7_span->rx_grs.range + 1); i++) { + /* confirm this is a voice channel, otherwise we do nothing */ + if (g_ftdm_sngss7_data.cfg.isupCkt[i].type != VOICE) { + continue; + } + /* extract the channel in question */ if (extract_chan_data(i, &sngss7_info, &ftdmchan)) { SS7_ERROR("Failed to extract channel data for circuit = %d!\n",i); @@ -638,13 +660,13 @@ ftdm_status_t check_if_rx_grs_processed(ftdm_span_t *ftdmspan) sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX_CMPLT); /* move the channel to the down state */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); /* update the status map if the ckt is in blocked state */ - if ((sngss7_test_ckt_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) || - (sngss7_test_ckt_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX)) || - (sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX)) || - (sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX))) { + if ((sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) || + (sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX)) || + (sngss7_test_ckt_blk_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX)) || + (sngss7_test_ckt_blk_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX))) { sngss7_span->rx_grs.status[byte] = (sngss7_span->rx_grs.status[byte] | (1 << bit)); } /* if blocked */ @@ -659,6 +681,12 @@ ftdm_status_t check_if_rx_grs_processed(ftdm_span_t *ftdmspan) GRS_UNLOCK_ALL: for ( i = sngss7_span->rx_grs.circuit; i < (sngss7_span->rx_grs.circuit + sngss7_span->rx_grs.range + 1); i++) { + + /* confirm this is a voice channel, otherwise we do nothing */ + if (g_ftdm_sngss7_data.cfg.isupCkt[i].type != VOICE) { + continue; + } + /* extract the channel in question */ if (extract_chan_data(i, &sngss7_info, &ftdmchan)) { SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i); @@ -680,6 +708,10 @@ ftdm_status_t check_if_rx_gra_started(ftdm_span_t *ftdmspan) sngss7_span_data_t *sngss7_span = (sngss7_span_data_t *)ftdmspan->signal_data; int i; + SS7_INFO("Rx GRA (%d:%d)\n", + g_ftdm_sngss7_data.cfg.isupCkt[sngss7_span->rx_gra.circuit].cic, + (g_ftdm_sngss7_data.cfg.isupCkt[sngss7_span->rx_gra.circuit].cic + sngss7_span->rx_gra.range)); + for (i = sngss7_span->rx_gra.circuit; i < (sngss7_span->rx_gra.circuit + sngss7_span->rx_gra.range + 1); i++) { /* extract the channel in question */ @@ -702,9 +734,7 @@ ftdm_status_t check_if_rx_gra_started(ftdm_span_t *ftdmspan) ftdm_sangoma_ss7_process_state_change (ftdmchan); } - SS7_INFO_CHAN(ftdmchan, "Rx GRA (%d:%d)\n", - g_ftdm_sngss7_data.cfg.isupCkt[sngss7_span->rx_gra.circuit].cic, - (g_ftdm_sngss7_data.cfg.isupCkt[sngss7_span->rx_gra.circuit].cic + sngss7_span->rx_gra.range)); + switch (ftdmchan->state) { /**********************************************************************/ @@ -714,7 +744,7 @@ ftdm_status_t check_if_rx_gra_started(ftdm_span_t *ftdmspan) sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP); /* go to DOWN */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); break; /**********************************************************************/ @@ -743,7 +773,7 @@ ftdm_status_t check_if_rx_gra_started(ftdm_span_t *ftdmspan) } /* go to terminating to hang up the call */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); break; /**********************************************************************/ } @@ -795,7 +825,7 @@ ftdm_status_t check_for_res_sus_flag(ftdm_span_t *ftdmspan) /* throw the channel into SUSPENDED to process the flag */ /* after doing this once the sig status will be down */ - ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); + ftdm_set_state (ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); } /* if the RESUME flag is up go to SUSPENDED to process the flag */ @@ -808,7 +838,7 @@ ftdm_status_t check_for_res_sus_flag(ftdm_span_t *ftdmspan) } /* got SUSPENDED state to clear the flag */ - ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); + ftdm_set_state (ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); } /* unlock the channel */ @@ -849,10 +879,10 @@ ftdm_status_t process_span_ucic(ftdm_span_t *ftdmspan) } /* throw the ckt block flag */ - sngss7_set_ckt_flag(sngss7_info, FLAG_CKT_UCIC_BLOCK); + sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_UCIC_BLOCK); /* set the channel to suspended state */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); /* unlock the channel again before we exit */ ftdm_mutex_unlock(ftdmchan->mutex); @@ -1348,6 +1378,147 @@ ftdm_status_t check_status_of_all_isup_intf(void) return FTDM_SUCCESS; } +/******************************************************************************/ +ftdm_status_t sngss7_add_var(sngss7_chan_data_t *sngss7_info, const char* var, const char* val) +{ + char *t_name = 0; + char *t_val = 0; + + /* confirm the user has sent us a value */ + if (!var || !val) { + return FTDM_FAIL; + } + + if (!sngss7_info->variables) { + /* initialize on first use */ + sngss7_info->variables = create_hashtable(16, ftdm_hash_hashfromstring, ftdm_hash_equalkeys); + ftdm_assert_return(sngss7_info->variables, FTDM_FAIL, "Failed to create hash table\n"); + } + + t_name = ftdm_strdup(var); + t_val = ftdm_strdup(val); + + hashtable_insert(sngss7_info->variables, t_name, t_val, HASHTABLE_FLAG_FREE_KEY | HASHTABLE_FLAG_FREE_VALUE); + + return FTDM_SUCCESS; +} + +/******************************************************************************/ +ftdm_status_t sngss7_add_raw_data(sngss7_chan_data_t *sngss7_info, uint8_t* data, ftdm_size_t data_len) +{ + ftdm_assert_return(!sngss7_info->raw_data, FTDM_FAIL, "Overwriting existing raw data\n"); + + sngss7_info->raw_data = ftdm_calloc(1, data_len); + ftdm_assert_return(sngss7_info->raw_data, FTDM_FAIL, "Failed to allocate raw data\n"); + + memcpy(sngss7_info->raw_data, data, data_len); + sngss7_info->raw_data_len = data_len; + return FTDM_SUCCESS; +} + +/******************************************************************************/ +void sngss7_send_signal(sngss7_chan_data_t *sngss7_info, ftdm_signal_event_t event_id) +{ + ftdm_sigmsg_t sigev; + ftdm_channel_t *ftdmchan = sngss7_info->ftdmchan; + + memset(&sigev, 0, sizeof(sigev)); + + sigev.chan_id = ftdmchan->chan_id; + sigev.span_id = ftdmchan->span_id; + sigev.channel = ftdmchan; + sigev.event_id = event_id; + + if (sngss7_info->variables) { + /* + * variables now belongs to the ftdm core, and + * will be cleared after sigev is processed by user. Set + * local pointer to NULL so we do not attempt to + * destroy it */ + sigev.variables = sngss7_info->variables; + sngss7_info->variables = NULL; + } + + if (sngss7_info->raw_data) { + /* + * raw_data now belongs to the ftdm core, and + * will be cleared after sigev is processed by user. Set + * local pointer to NULL so we do not attempt to + * destroy it */ + + sigev.raw.data = sngss7_info->raw_data; + sigev.raw.len = sngss7_info->raw_data_len; + + sngss7_info->raw_data = NULL; + sngss7_info->raw_data_len = 0; + } + ftdm_span_send_signal(ftdmchan->span, &sigev); +} + +/******************************************************************************/ +void sngss7_set_sig_status(sngss7_chan_data_t *sngss7_info, ftdm_signaling_status_t status) +{ + ftdm_sigmsg_t sig; + ftdm_channel_t *ftdmchan = sngss7_info->ftdmchan; + + SS7_DEBUG_CHAN(ftdmchan, "Signalling link status changed to %s\n", + ftdm_signaling_status2str(status)); + + memset(&sig, 0, sizeof(sig)); + + sig.chan_id = ftdmchan->chan_id; + sig.span_id = ftdmchan->span_id; + sig.channel = ftdmchan; + sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; + sig.ev_data.sigstatus.status = status; + + if (ftdm_span_send_signal(ftdmchan->span, &sig) != FTDM_SUCCESS) { + SS7_ERROR_CHAN(ftdmchan, "Failed to change channel status to %s\n", + ftdm_signaling_status2str(status)); + } + return; +} + +/******************************************************************************/ +ftdm_status_t check_for_reconfig_flag(ftdm_span_t *ftdmspan) +{ + ftdm_channel_t *ftdmchan = NULL; + sngss7_chan_data_t *sngss7_info = NULL; + int x; + int ret; + + for (x = 1; x < (ftdmspan->chan_count + 1); x++) { + /**************************************************************************/ + /* extract the channel structure and sngss7 channel data */ + ftdmchan = ftdmspan->channels[x]; + + /* if the call data is NULL move on */ + if (ftdmchan->call_data == NULL) { + SS7_WARN_CHAN(ftdmchan, "Reconfiguring channel that has not call_data!%s\n", " "); + continue; + } + + /* grab the private data */ + sngss7_info = ftdmchan->call_data; + + /* check the reconfig flag */ + if (sngss7_test_ckt_flag(sngss7_info, FLAG_CKT_RECONFIG)) { + ret = ftmod_ss7_isup_ckt_config(sngss7_info->circuit->id); + + if (ret) { + SS7_CRITICAL("ISUP CKT %d re-configuration FAILED!\n", x); + } else { + SS7_INFO("ISUP CKT %d re-configuration DONE!\n", x); + } + + /* clear the re-config flag ... no matter what */ + sngss7_clear_ckt_flag(sngss7_info, FLAG_CKT_RECONFIG); + + } /* if ((sngss7_test_ckt_flag(sngss7_info, FLAG_CKT_RECONFIG)) */ + } /* for (x = 1; x < (span->chan_count + 1); x++) */ + + return FTDM_SUCCESS; +} /******************************************************************************/ /* For Emacs: * Local Variables: diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_timers.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_timers.c index c2d493f34e..ff66cc6b41 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_timers.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_timers.c @@ -67,7 +67,7 @@ void handle_isup_t35(void *userdata) ftdmchan->caller_data.hangup_cause = 28; /* end the call */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_CANCEL); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_CANCEL); /*unlock*/ ftdm_mutex_unlock(ftdmchan->mutex); diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c index 166fe5dc04..49da10cdf1 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c @@ -2668,7 +2668,7 @@ static int ftmod_ss7_fill_in_isup_interface(sng_isup_inf_t *sng_isup) if (sng_isup->tpause != 0) { g_ftdm_sngss7_data.cfg.isupIntf[i].tpause = sng_isup->tpause; } else { - g_ftdm_sngss7_data.cfg.isupIntf[i].tpause = 150; + g_ftdm_sngss7_data.cfg.isupIntf[i].tpause = 3000; } if (sng_isup->tstaenq != 0) { g_ftdm_sngss7_data.cfg.isupIntf[i].tstaenq = sng_isup->tstaenq; diff --git a/libs/freetdm/src/include/freetdm.h b/libs/freetdm/src/include/freetdm.h old mode 100644 new mode 100755 index ef7843e5cc..6556164aac --- a/libs/freetdm/src/include/freetdm.h +++ b/libs/freetdm/src/include/freetdm.h @@ -172,7 +172,7 @@ typedef enum { /*! \brief I/O channel type */ typedef enum { FTDM_CHAN_TYPE_B, /*!< Bearer channel */ - FTDM_CHAN_TYPE_DQ921, /*< DQ921 channel (D-channel) */ + FTDM_CHAN_TYPE_DQ921, /*!< DQ921 channel (D-channel) */ FTDM_CHAN_TYPE_DQ931, /*!< DQ931 channel */ FTDM_CHAN_TYPE_FXS, /*!< FXS analog channel */ FTDM_CHAN_TYPE_FXO, /*!< FXO analog channel */ @@ -214,6 +214,7 @@ typedef void *(*ftdm_queue_dequeue_func_t)(ftdm_queue_t *queue); typedef ftdm_status_t (*ftdm_queue_wait_func_t)(ftdm_queue_t *queue, int ms); typedef ftdm_status_t (*ftdm_queue_get_interrupt_func_t)(ftdm_queue_t *queue, ftdm_interrupt_t **interrupt); typedef ftdm_status_t (*ftdm_queue_destroy_func_t)(ftdm_queue_t **queue); + typedef struct ftdm_queue_handler { ftdm_queue_create_func_t create; ftdm_queue_enqueue_func_t enqueue; @@ -223,7 +224,6 @@ typedef struct ftdm_queue_handler { ftdm_queue_destroy_func_t destroy; } ftdm_queue_handler_t; - /*! \brief Type Of Number (TON) */ typedef enum { FTDM_TON_UNKNOWN = 0, @@ -318,8 +318,6 @@ typedef struct { uint8_t plan; } ftdm_number_t; -typedef void * ftdm_variable_container_t; - /*! \brief Caller information */ typedef struct ftdm_caller_data { char cid_date[8]; /*!< Caller ID date */ @@ -333,21 +331,23 @@ typedef struct ftdm_caller_data { uint8_t pres; /*!< Presentation*/ char collected[FTDM_DIGITS_LIMIT]; /*!< Collected digits so far */ int hangup_cause; /*!< Hangup cause */ - char raw_data[1024]; /*!< Protocol specific raw caller data */ - uint32_t raw_data_len; /*!< Raw data length */ /* these 2 are undocumented right now, only used by boost: */ /* bearer capability */ ftdm_bearer_cap_t bearer_capability; /* user information layer 1 protocol */ ftdm_user_layer1_prot_t bearer_layer1; ftdm_calling_party_category_t cpc; /*!< Calling party category */ - ftdm_variable_container_t variables; /*!< Variables attached to this call */ - /* We need call_id inside caller_data for the user to be able to retrieve + + ftdm_channel_t *fchan; /*!< FreeTDM channel associated (can be NULL) */ + + /* + * We need call_id inside caller_data for the user to be able to retrieve * the call_id when ftdm_channel_call_place is called. This is the only time * that the user can use caller_data.call_id to obtain the call_id. The user - * should use the call_id from sigmsg otherwise */ + * should use the call_id from sigmsg otherwise + */ uint32_t call_id; /*!< Unique call ID for this call */ - ftdm_channel_t *fchan; /*!< FreeTDM channel associated (can be NULL) */ + void *priv; /*!< Private data for the FreeTDM user */ } ftdm_caller_data_t; @@ -533,9 +533,10 @@ typedef enum { FTDM_CHANNEL_INDICATE_BUSY, /* Using this indication is equivalent to call ftdm_channel_call_answer API */ FTDM_CHANNEL_INDICATE_ANSWER, + FTDM_CHANNEL_INDICATE_FACILITY, FTDM_CHANNEL_INDICATE_INVALID, } ftdm_channel_indication_t; -#define INDICATION_STRINGS "NONE", "RINGING", "PROCEED", "PROGRESS", "PROGRESS_MEDIA", "BUSY", "ANSWER", "INVALID" +#define INDICATION_STRINGS "NONE", "RINGING", "PROCEED", "PROGRESS", "PROGRESS_MEDIA", "BUSY", "ANSWER", "FACILITY", "INVALID" /*! \brief Move from string to ftdm_channel_indication_t and viceversa */ FTDM_STR2ENUM_P(ftdm_str2channel_indication, ftdm_channel_indication2str, ftdm_channel_indication_t) @@ -547,7 +548,14 @@ typedef struct { ftdm_status_t status; } ftdm_event_indication_completed_t; -/*! \brief Generic signaling message */ +typedef void * ftdm_variable_container_t; + +typedef struct { + ftdm_size_t len; + void *data; +} ftdm_raw_data_t; + +/*! \brief Generic signaling message received from the stack */ struct ftdm_sigmsg { ftdm_signal_event_t event_id; /*!< The type of message */ ftdm_channel_t *channel; /*!< Related channel */ @@ -555,17 +563,20 @@ struct ftdm_sigmsg { uint32_t span_id; /*!< easy access to span_id */ uint32_t call_id; /*!< unique call id for this call */ void *call_priv; /*!< Private data for the FreeTDM user from ftdm_caller_data->priv */ + ftdm_variable_container_t variables; union { ftdm_event_sigstatus_t sigstatus; /*!< valid if event_id is FTDM_SIGEVENT_SIGSTATUS_CHANGED */ ftdm_event_trace_t trace; /*!< valid if event_id is FTDM_SIGEVENT_TRACE or FTDM_SIGEVENT_TRACE_RAW */ ftdm_event_collected_t collected; /*!< valid if event_id is FTDM_SIGEVENT_COLLECTED_DIGIT */ ftdm_event_indication_completed_t indication_completed; /*!< valid if the event_id is FTDM_SIGEVENT_INDICATION_COMPLETED */ } ev_data; - struct { - uint8_t autofree; /*!< Whether the freetdm core will free it after message delivery */ - uint32_t len; /*!< Data len */ - void *data; /*!< Signaling module specific data */ - } raw; + ftdm_raw_data_t raw; +}; + +/*! \brief Generic user message sent to the stack */ +struct ftdm_usrmsg { + ftdm_variable_container_t variables; + ftdm_raw_data_t raw; }; /*! \brief Crash policy @@ -673,6 +684,9 @@ typedef enum { FTDM_COMMAND_SET_RX_QUEUE_SIZE = 54, FTDM_COMMAND_SET_TX_QUEUE_SIZE = 55, FTDM_COMMAND_SET_POLARITY = 56, + FTDM_COMMAND_START_MF_PLAYBACK = 57, + FTDM_COMMAND_STOP_MF_PLAYBACK = 58, + FTDM_COMMAND_COUNT, } ftdm_command_t; @@ -698,7 +712,7 @@ struct ftdm_memory_handler { * You don't need these unless your implementing an I/O interface module (most users don't) */ #define FIO_CHANNEL_REQUEST_ARGS (ftdm_span_t *span, uint32_t chan_id, ftdm_direction_t direction, ftdm_caller_data_t *caller_data, ftdm_channel_t **ftdmchan) #define FIO_CHANNEL_OUTGOING_CALL_ARGS (ftdm_channel_t *ftdmchan) -#define FIO_CHANNEL_SEND_MSG_ARGS (ftdm_channel_t *ftdmchan, ftdm_sigmsg_t *sigmsg) +#define FIO_CHANNEL_INDICATE_ARGS (ftdm_channel_t *ftdmchan, ftdm_channel_indication_t indication) #define FIO_CHANNEL_SET_SIG_STATUS_ARGS (ftdm_channel_t *ftdmchan, ftdm_signaling_status_t status) #define FIO_CHANNEL_GET_SIG_STATUS_ARGS (ftdm_channel_t *ftdmchan, ftdm_signaling_status_t *status) #define FIO_SPAN_SET_SIG_STATUS_ARGS (ftdm_span_t *span, ftdm_signaling_status_t status) @@ -731,7 +745,7 @@ struct ftdm_memory_handler { * You don't need these unless your implementing an I/O interface module (most users don't) */ typedef ftdm_status_t (*fio_channel_request_t) FIO_CHANNEL_REQUEST_ARGS ; typedef ftdm_status_t (*fio_channel_outgoing_call_t) FIO_CHANNEL_OUTGOING_CALL_ARGS ; -typedef ftdm_status_t (*fio_channel_send_msg_t) FIO_CHANNEL_SEND_MSG_ARGS; +typedef ftdm_status_t (*fio_channel_indicate_t) FIO_CHANNEL_INDICATE_ARGS; typedef ftdm_status_t (*fio_channel_set_sig_status_t) FIO_CHANNEL_SET_SIG_STATUS_ARGS; typedef ftdm_status_t (*fio_channel_get_sig_status_t) FIO_CHANNEL_GET_SIG_STATUS_ARGS; typedef ftdm_status_t (*fio_span_set_sig_status_t) FIO_SPAN_SET_SIG_STATUS_ARGS; @@ -778,7 +792,7 @@ typedef ftdm_status_t (*fio_api_t) FIO_API_ARGS ; * You don't need these unless your implementing an I/O interface module (most users don't) */ #define FIO_CHANNEL_REQUEST_FUNCTION(name) ftdm_status_t name FIO_CHANNEL_REQUEST_ARGS #define FIO_CHANNEL_OUTGOING_CALL_FUNCTION(name) ftdm_status_t name FIO_CHANNEL_OUTGOING_CALL_ARGS -#define FIO_CHANNEL_SEND_MSG_FUNCTION(name) ftdm_status_t name FIO_CHANNEL_SEND_MSG_ARGS +#define FIO_CHANNEL_INDICATE_FUNCTION(name) ftdm_status_t name FIO_CHANNEL_INDICATE_ARGS #define FIO_CHANNEL_SET_SIG_STATUS_FUNCTION(name) ftdm_status_t name FIO_CHANNEL_SET_SIG_STATUS_ARGS #define FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(name) ftdm_status_t name FIO_CHANNEL_GET_SIG_STATUS_ARGS #define FIO_SPAN_SET_SIG_STATUS_FUNCTION(name) ftdm_status_t name FIO_SPAN_SET_SIG_STATUS_ARGS @@ -847,6 +861,16 @@ typedef enum { FTDM_ALARM_GENERAL = (1 << 30) } ftdm_alarm_flag_t; +/*! \brief MF generation direction flags + * \note Used in bitwise OR with channel ID as argument to MF_PLAYBACK I/O command, so value must be higher that 255 + * \see FTDM_COMMAND_START_MF_PLAYBACK + * */ + +typedef enum { + FTDM_MF_DIRECTION_FORWARD = (1 << 8), + FTDM_MF_DIRECTION_BACKWARD = (1 << 9) +} ftdm_mf_direction_flag_t; + /*! \brief Override the default queue handler */ FT_DECLARE(ftdm_status_t) ftdm_global_set_queue_handler(ftdm_queue_handler_t *handler); @@ -866,23 +890,26 @@ FT_DECLARE(int) ftdm_channel_get_availability(ftdm_channel_t *ftdmchan); * there is no guarantee of whether the event will arrive after or before your execution thread returns * from ftdm_channel_call_answer */ -#define ftdm_channel_call_answer(ftdmchan) _ftdm_channel_call_answer(__FILE__, __FUNCTION__, __LINE__, (ftdmchan)) +#define ftdm_channel_call_answer(ftdmchan) _ftdm_channel_call_answer(__FILE__, __FUNCTION__, __LINE__, (ftdmchan), NULL) +#define ftdm_channel_call_answer_ex(ftdmchan, usrmsg) _ftdm_channel_call_answer(__FILE__, __FUNCTION__, __LINE__, (ftdmchan), (usrmsg)) /*! \brief Answer call recording the source code point where the it was called (see ftdm_channel_call_answer for an easy to use macro) */ -FT_DECLARE(ftdm_status_t) _ftdm_channel_call_answer(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan); +FT_DECLARE(ftdm_status_t) _ftdm_channel_call_answer(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_usrmsg_t *usrmsg); /*! \brief Place an outgoing call in the given channel * \deprecated This macro is deprecated since leaves the door open to glare issues, use ftdm_call_place instead */ -#define ftdm_channel_call_place(ftdmchan) _ftdm_channel_call_place(__FILE__, __FUNCTION__, __LINE__, (ftdmchan)) +#define ftdm_channel_call_place(ftdmchan) _ftdm_channel_call_place(__FILE__, __FUNCTION__, __LINE__, (ftdmchan), NULL) +#define ftdm_channel_call_place_ex(ftdmchan, usrmsg) _ftdm_channel_call_place_ex(__FILE__, __FUNCTION__, __LINE__, (ftdmchan), (usrmsg)) /*! \brief Place an outgoing call recording the source code point where it was called (see ftdm_channel_call_place for an easy to use macro) * \deprecated This function is deprecated since leaves the door open to glare issues, use ftdm_call_place instead */ -FT_DECLARE(ftdm_status_t) _ftdm_channel_call_place(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan); +FT_DECLARE(ftdm_status_t) _ftdm_channel_call_place(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_usrmsg_t *usrmsg); /*! \brief Place an outgoing call with the given caller data in a channel according to the hunting scheme provided */ -#define ftdm_call_place(callerdata, hunting) _ftdm_call_place(__FILE__, __FUNCTION__, __LINE__, (callerdata), (hunting)) +#define ftdm_call_place(callerdata, hunting) _ftdm_call_place(__FILE__, __FUNCTION__, __LINE__, (callerdata), (hunting), NULL) +#define ftdm_call_place_ex(callerdata, hunting, usrmsg) _ftdm_call_place(__FILE__, __FUNCTION__, __LINE__, (callerdata), (hunting), (usrmsg)) /*! \brief Place an outgoing call with the given caller data in a channel according to the hunting scheme provided and records * the place where it was called. See ftdm_call_place for an easy to use macro @@ -899,7 +926,7 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_place(const char *file, const char * \note When this function is successful you are guaranteed to receive FTDM_SIGEVENT_DIALING, this event could even be delivered * before your execution thread returns from this function */ -FT_DECLARE(ftdm_status_t) _ftdm_call_place(const char *file, const char *func, int line, ftdm_caller_data_t *caller_data, ftdm_hunting_scheme_t *hunting); +FT_DECLARE(ftdm_status_t) _ftdm_call_place(const char *file, const char *func, int line, ftdm_caller_data_t *caller_data, ftdm_hunting_scheme_t *hunting, ftdm_usrmsg_t *usrmsg); /*! \brief Indicate a new condition in an incoming call * @@ -914,48 +941,48 @@ FT_DECLARE(ftdm_status_t) _ftdm_call_place(const char *file, const char *func, i * \note You cannot send more than one indication at the time. You must wait for the completed event before * calling this function again (unless the return code was different than FTDM_SUCCESS) */ -#define ftdm_channel_call_indicate(ftdmchan, indication) _ftdm_channel_call_indicate(__FILE__, __FUNCTION__, __LINE__, (ftdmchan), (indication)) +#define ftdm_channel_call_indicate(ftdmchan, indication) _ftdm_channel_call_indicate(__FILE__, __FUNCTION__, __LINE__, (ftdmchan), (indication), NULL) +#define ftdm_channel_call_indicate_ex(ftdmchan, indication, usrmsg) _ftdm_channel_call_indicate(__FILE__, __FUNCTION__, __LINE__, (ftdmchan), (indication), (usrmsg)) /*! \brief Indicate a new condition in an incoming call recording the source code point where it was called (see ftdm_channel_call_indicate for an easy to use macro) */ -FT_DECLARE(ftdm_status_t) _ftdm_channel_call_indicate(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_channel_indication_t indication); - -/*! \brief Send a message on a call */ -#define ftdm_channel_call_send_msg(ftdmchan, sigmsg) _ftdm_channel_call_send_msg(__FILE__, __FUNCTION__, __LINE__, (ftdmchan), (sigmsg)) - -/*! \brief Send a signal on a call recording the source code point where it was called (see ftdm_channel_call_send_msg for an easy to use macro) */ -FT_DECLARE(ftdm_status_t) _ftdm_channel_call_send_msg(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_sigmsg_t *sigmsg); +FT_DECLARE(ftdm_status_t) _ftdm_channel_call_indicate(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_channel_indication_t indication, ftdm_usrmsg_t *usrmsg); /*! \brief Hangup the call without cause */ -#define ftdm_channel_call_hangup(ftdmchan) _ftdm_channel_call_hangup(__FILE__, __FUNCTION__, __LINE__, (ftdmchan)) +#define ftdm_channel_call_hangup(ftdmchan) _ftdm_channel_call_hangup(__FILE__, __FUNCTION__, __LINE__, (ftdmchan), NULL) +#define ftdm_channel_call_hangup_ex(ftdmchan, usrmsg) _ftdm_channel_call_hangup(__FILE__, __FUNCTION__, __LINE__, (ftdmchan), (usrmsg)) /*! \brief Hangup the call without cause recording the source code point where it was called (see ftdm_channel_call_hangup for an easy to use macro)*/ -FT_DECLARE(ftdm_status_t) _ftdm_channel_call_hangup(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan); +FT_DECLARE(ftdm_status_t) _ftdm_channel_call_hangup(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_usrmsg_t *usrmsg); /*! \brief Hangup the call with cause */ -#define ftdm_channel_call_hangup_with_cause(ftdmchan, cause) _ftdm_channel_call_hangup_with_cause(__FILE__, __FUNCTION__, __LINE__, (ftdmchan), (cause)) +#define ftdm_channel_call_hangup_with_cause(ftdmchan, cause) _ftdm_channel_call_hangup_with_cause(__FILE__, __FUNCTION__, __LINE__, (ftdmchan), (cause), NULL) +#define ftdm_channel_call_hangup_with_cause_ex(ftdmchan, cause, usrmsg) _ftdm_channel_call_hangup_with_cause(__FILE__, __FUNCTION__, __LINE__, (ftdmchan), (cause), (usrmsg)) /*! \brief Hangup the call with cause recording the source code point where it was called (see ftdm_channel_call_hangup_with_cause for an easy to use macro) */ -FT_DECLARE(ftdm_status_t) _ftdm_channel_call_hangup_with_cause(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_call_cause_t); +FT_DECLARE(ftdm_status_t) _ftdm_channel_call_hangup_with_cause(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_call_cause_t, ftdm_usrmsg_t *usrmsg); /*! \brief Reset the channel */ -#define ftdm_channel_reset(ftdmchan) _ftdm_channel_reset(__FILE__, __FUNCTION__, __LINE__, (ftdmchan)) +#define ftdm_channel_reset(ftdmchan) _ftdm_channel_reset(__FILE__, __FUNCTION__, __LINE__, (ftdmchan), NULL) +#define ftdm_channel_reset_ex(ftdmchan, usrmsg) _ftdm_channel_reset(__FILE__, __FUNCTION__, __LINE__, (ftdmchan), usrmsg) /*! \brief Reset the channel (see _ftdm_channel_reset for an easy to use macro) * \note if there was a call on this channel, call will be cleared without any notifications to the user */ -FT_DECLARE(ftdm_status_t) _ftdm_channel_reset(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan); +FT_DECLARE(ftdm_status_t) _ftdm_channel_reset(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_usrmsg_t *usrmsg); /*! \brief Put a call on hold (if supported by the signaling stack) */ -#define ftdm_channel_call_hold(ftdmchan) _ftdm_channel_call_hold(__FILE__, __FUNCTION__, __LINE__, (ftdmchan)) +#define ftdm_channel_call_hold(ftdmchan) _ftdm_channel_call_hold(__FILE__, __FUNCTION__, __LINE__, (ftdmchan), NULL) +#define ftdm_channel_call_hold_ex(ftdmchan, usrmsg) _ftdm_channel_call_hold(__FILE__, __FUNCTION__, __LINE__, (ftdmchan), (usrmsg)) /*! \brief Put a call on hold recording the source code point where it was called (see ftdm_channel_call_hold for an easy to use macro) */ -FT_DECLARE(ftdm_status_t) _ftdm_channel_call_hold(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan); +FT_DECLARE(ftdm_status_t) _ftdm_channel_call_hold(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_usrmsg_t *usrmsg); /*! \brief Unhold a call */ -#define ftdm_channel_call_unhold(ftdmchan) _ftdm_channel_call_unhold(__FILE__, __FUNCTION__, __LINE__, (ftdmchan)) +#define ftdm_channel_call_unhold(ftdmchan) _ftdm_channel_call_unhold(__FILE__, __FUNCTION__, __LINE__, (ftdmchan), NULL) +#define ftdm_channel_call_unhold_ex(ftdmchan, usrmsg) _ftdm_channel_call_unhold(__FILE__, __FUNCTION__, __LINE__, (ftdmchan), (usrmsg)) /*! \brief Unhold a call recording the source code point where it was called (see ftdm_channel_call_unhold for an easy to use macro) */ -FT_DECLARE(ftdm_status_t) _ftdm_channel_call_unhold(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan); +FT_DECLARE(ftdm_status_t) _ftdm_channel_call_unhold(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_usrmsg_t *usrmsg); /*! \brief Check if the call is answered already */ FT_DECLARE(ftdm_bool_t) ftdm_channel_call_check_answered(const ftdm_channel_t *ftdmchan); @@ -1369,12 +1396,65 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_read(ftdm_channel_t *ftdmchan, void *data */ FT_DECLARE(ftdm_status_t) ftdm_channel_write(ftdm_channel_t *ftdmchan, void *data, ftdm_size_t datasize, ftdm_size_t *datalen); +/*! \brief Get a custom variable from the sigmsg + * \note The variable pointer returned is only valid while the before the event is processed and it'll be destroyed once the event is processed. */ +FT_DECLARE(const char *) ftdm_sigmsg_get_var(ftdm_sigmsg_t *sigmsg, const char *var_name); + +/*! \brief Get an iterator to iterate over the sigmsg variables + * \param sigmsg The message structure containing the variables + * \param iter Optional iterator. You can reuse an old iterator (not previously freed) to avoid the extra allocation of a new iterator. + * \note The iterator pointer returned is only valid while the channel is open and it'll be destroyed when the channel is closed. + * This iterator is completely non-thread safe, if you are adding variables or removing variables while iterating + * results are unpredictable + */ +FT_DECLARE(ftdm_iterator_t *) ftdm_sigmsg_get_var_iterator(const ftdm_sigmsg_t *sigmsg, ftdm_iterator_t *iter); + +/*! \brief Get raw data from sigmsg + * \param sigmsg The message structure containing the variables + * \param data data will point to available data pointer if available + * \param datalen datalen will be set to length of data available + * \retval FTDM_SUCCESS data is available + * \retval FTDM_FAIL no data available + * \note data is only valid within the duration of the callback, to receive a data pointer that does not get + * \note destroyed when callback returns, see ftdm_sigmsg_get_raw_data_detached + */ +FT_DECLARE(ftdm_status_t) ftdm_sigmsg_get_raw_data(ftdm_sigmsg_t *sigmsg, void **data, ftdm_size_t *datalen); + +/*! \brief Get raw data from event + * \param sigmsg The message structure containing the variables + * \param data data will point to available data pointer if available + * \param datalen datalen will be set to length of data available + * \retval FTDM_SUCCESS data is available + * \retval FTDM_FAIL no data available + * \note Once this function returns, User owns data, and is responsible to free data using ftdm_safe_free(); + */ +FT_DECLARE(ftdm_status_t) ftdm_sigmsg_get_raw_data_detached(ftdm_sigmsg_t *sigmsg, void **data, ftdm_size_t *datalen); + +/*! \brief Add a custom variable to the user message + * \note This variables may be used by signaling modules to override signaling parameters + * \todo Document which signaling variables are available + * */ +FT_DECLARE(ftdm_status_t) ftdm_usrmsg_add_var(ftdm_usrmsg_t *usrmsg, const char *var_name, const char *value); + +/*! \brief Attach raw data to usrmsg + * \param usrmsg The message structure containing the variables + * \param data pointer to data + * \param datalen datalen length of data + * \retval FTDM_SUCCESS success, data was successfully saved + * \retval FTDM_FAIL failed, event already had data attached to it. + * \note data must have been allocated using ftdm_calloc, FreeTDM will free data once the usrmsg is processed. + */ +FT_DECLARE(ftdm_status_t) ftdm_usrmsg_set_raw_data(ftdm_usrmsg_t *usrmsg, void *data, ftdm_size_t datalen); + /*! \brief Get iterator current value (depends on the iterator type) * \note Channel iterators return a pointer to ftdm_channel_t * Variable iterators return a pointer to the variable name (not the variable value) */ FT_DECLARE(void *) ftdm_iterator_current(ftdm_iterator_t *iter); +/*! \brief Get variable name and value for the current iterator position */ +FT_DECLARE(ftdm_status_t) ftdm_get_current_var(ftdm_iterator_t *iter, const char **var_name, const char **var_val); + /*! \brief Advance iterator */ FT_DECLARE(ftdm_iterator_t *) ftdm_iterator_next(ftdm_iterator_t *iter); @@ -1383,28 +1463,11 @@ FT_DECLARE(ftdm_iterator_t *) ftdm_iterator_next(ftdm_iterator_t *iter); */ FT_DECLARE(ftdm_status_t) ftdm_iterator_free(ftdm_iterator_t *iter); -/*! \brief Add a custom variable to the call - * \note This variables may be used by signaling modules to override signaling parameters - * \todo Document which signaling variables are available +/*! \brief Clears all the temporary data attached to this call + * \note Clears caller_data->variables and caller_data->raw_data. * */ -FT_DECLARE(ftdm_status_t) ftdm_call_add_var(ftdm_caller_data_t *caller_data, const char *var_name, const char *value); - -/*! \brief Get a custom variable from the call. - * \note The variable pointer returned is only valid during the callback receiving SIGEVENT. */ -FT_DECLARE(const char *) ftdm_call_get_var(ftdm_caller_data_t *caller_data, const char *var_name); - -/*! \brief Get an iterator to iterate over the channel variables - * \param caller_data The signal msg structure containing the variables - * \param iter Optional iterator. You can reuse an old iterator (not previously freed) to avoid the extra allocation of a new iterator. - * \note The iterator pointer returned is only valid while the signal message and it'll be destroyed when the signal message is processed. - * This iterator is completely non-thread safe, if you are adding variables or removing variables while iterating - * results are unpredictable - */ -FT_DECLARE(ftdm_iterator_t *) ftdm_call_get_var_iterator(const ftdm_caller_data_t *caller_data, ftdm_iterator_t *iter); - -/*! \brief Get variable name and value for the current iterator position */ -FT_DECLARE(ftdm_status_t) ftdm_call_get_current_var(ftdm_iterator_t *iter, const char **var_name, const char **var_val); - +FT_DECLARE(void) ftdm_call_clear_data(ftdm_caller_data_t *caller_data); + /*! \brief Get the span pointer associated to the channel */ FT_DECLARE(ftdm_span_t *) ftdm_channel_get_span(const ftdm_channel_t *ftdmchan); @@ -1632,11 +1695,6 @@ FT_DECLARE(const char *) ftdm_channel_get_last_state_str(const ftdm_channel_t *c */ FT_DECLARE(char *) ftdm_channel_get_history_str(const ftdm_channel_t *channel); -/*! \brief Initialize channel state for an outgoing call - * \deprecated This API is only used for boost signaling - */ -FT_DECLARE(ftdm_status_t) ftdm_channel_init(ftdm_channel_t *ftdmchan); - /*! \brief Enable/disable blocking mode in the channels for this span */ FT_DECLARE(ftdm_status_t) ftdm_span_set_blocking_mode(const ftdm_span_t *span, ftdm_bool_t enabled); diff --git a/libs/freetdm/src/include/ftdm_declare.h b/libs/freetdm/src/include/ftdm_declare.h index b443f2d5f5..9c7f9cbe4a 100644 --- a/libs/freetdm/src/include/ftdm_declare.h +++ b/libs/freetdm/src/include/ftdm_declare.h @@ -223,6 +223,7 @@ typedef struct ftdm_conf_node ftdm_conf_node_t; typedef struct ftdm_group ftdm_group_t; typedef size_t ftdm_size_t; typedef struct ftdm_sigmsg ftdm_sigmsg_t; +typedef struct ftdm_usrmsg ftdm_usrmsg_t; typedef struct ftdm_io_interface ftdm_io_interface_t; typedef struct ftdm_stream_handle ftdm_stream_handle_t; typedef struct ftdm_queue ftdm_queue_t; diff --git a/libs/freetdm/src/include/ftdm_dso.h b/libs/freetdm/src/include/ftdm_dso.h old mode 100644 new mode 100755 index b56ad93e39..8cdc13cba4 --- a/libs/freetdm/src/include/ftdm_dso.h +++ b/libs/freetdm/src/include/ftdm_dso.h @@ -49,6 +49,6 @@ FT_DECLARE(char *) ftdm_build_dso_path(const char *name, char *path, ftdm_size_t * c-basic-offset:4 * End: * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 + * vim:set softtabstop=4 shiftwidth=4 tabstop=4: */ diff --git a/libs/freetdm/src/include/private/ftdm_core.h b/libs/freetdm/src/include/private/ftdm_core.h index 0de52727da..c2de07b3f1 100644 --- a/libs/freetdm/src/include/private/ftdm_core.h +++ b/libs/freetdm/src/include/private/ftdm_core.h @@ -467,6 +467,7 @@ struct ftdm_channel { ftdm_interrupt_t *state_completed_interrupt; /*!< Notify when a state change is completed */ int32_t txdrops; int32_t rxdrops; + ftdm_usrmsg_t *usrmsg; }; struct ftdm_span { @@ -492,7 +493,7 @@ struct ftdm_span { teletone_multi_tone_t tone_finder[FTDM_TONEMAP_INVALID+1]; ftdm_channel_t *channels[FTDM_MAX_CHANNELS_SPAN+1]; fio_channel_outgoing_call_t outgoing_call; - fio_channel_send_msg_t send_msg; + fio_channel_indicate_t indicate; fio_channel_set_sig_status_t set_channel_sig_status; fio_channel_get_sig_status_t get_channel_sig_status; fio_span_set_sig_status_t set_span_sig_status; @@ -587,6 +588,10 @@ FT_DECLARE(ftdm_status_t) ftdm_span_close_all(void); FT_DECLARE(ftdm_status_t) ftdm_channel_open_chan(ftdm_channel_t *ftdmchan); FT_DECLARE(void) ftdm_ack_indication(ftdm_channel_t *ftdmchan, ftdm_channel_indication_t indication, ftdm_status_t status); + +FT_DECLARE(ftdm_iterator_t *) ftdm_get_iterator(ftdm_iterator_type_t type, ftdm_iterator_t *iter); + + /*! * \brief Retrieves an event from the span * @@ -624,27 +629,55 @@ FT_DECLARE(ftdm_status_t) ftdm_span_trigger_signals(const ftdm_span_t *span); /*! \brief clear the tone detector state */ FT_DECLARE(void) ftdm_channel_clear_detected_tones(ftdm_channel_t *ftdmchan); -/* start/stop echo cancelling at the beginning/end of a call */ +/*! \brief adjust echocanceller for beginning of call */ FT_DECLARE(void) ftdm_set_echocancel_call_begin(ftdm_channel_t *chan); + +/*! \brief adjust echocanceller for end of call */ FT_DECLARE(void) ftdm_set_echocancel_call_end(ftdm_channel_t *chan); -/*! \brief Clear all variables attached to the call - * \note Variables are cleared at the end of each call back, so it is not necessary for the user to call this function. +/*! \brief save data from user */ +FT_DECLARE(ftdm_status_t) ftdm_channel_save_usrmsg(ftdm_channel_t *ftdmchan, ftdm_usrmsg_t *usrmsg); + +/*! \brief free usrmsg and variables/raw data attached to it */ +FT_DECLARE(ftdm_status_t) ftdm_usrmsg_free(ftdm_usrmsg_t **usrmsg); + +/*! \brief Get a custom variable from the user message + * \note The variable pointer returned is only valid while the before the event is processed and it'll be destroyed once the event is processed. */ +FT_DECLARE(const char *) ftdm_usrmsg_get_var(ftdm_usrmsg_t *usrmsg, const char *var_name); + +/*! \brief Get raw data from user message + * \param usrmsg The message structure containing the variables + * \param data data will point to available data pointer if available + * \param datalen datalen will be set to length of data available + * \retval FTDM_SUCCESS data is available + * \retval FTDM_FAIL no data available + * \note data is only valid within the duration of the callback, to receive a data pointer that does not get + * \note destroyed when callback returns, see ftdm_sigmsg_get_raw_data_detached + */ +FT_DECLARE(ftdm_status_t) ftdm_usrmsg_get_raw_data(ftdm_usrmsg_t *usrmsg, void **data, ftdm_size_t *datalen); + +/*! \brief free sigmsg and variables/raw data attached to it */ +FT_DECLARE(ftdm_status_t) ftdm_sigmsg_free(ftdm_sigmsg_t **sigmsg); + +/*! \brief Add a custom variable to the event + * \note This variables may be used by signaling modules to override signaling parameters * \todo Document which signaling variables are available * */ -FT_DECLARE(ftdm_status_t) ftdm_call_clear_vars(ftdm_caller_data_t *caller_data); +FT_DECLARE(ftdm_status_t) ftdm_sigmsg_add_var(ftdm_sigmsg_t *sigmsg, const char *var_name, const char *value); -/*! \brief Remove a variable attached to the call - * \note Removes a variable that was attached to the call. - * \todo Document which call variables are available - * */ -FT_DECLARE(ftdm_status_t) ftdm_call_remove_var(ftdm_caller_data_t *caller_data, const char *var_name); +/*! \brief Remove a custom variable from the event + * \note The variable pointer returned is only valid while the before the event is processed and it'll be destroyed once the event is processed. */ +FT_DECLARE(ftdm_status_t) ftdm_sigmsg_remove_var(ftdm_sigmsg_t *sigmsg, const char *var_name); -/*! \brief Clears all the temporary data attached to this call - * \note Clears caller_data->variables and caller_data->raw_data. - * */ -FT_DECLARE(void) ftdm_call_clear_data(ftdm_caller_data_t *caller_data); - +/*! \brief Attach raw data to sigmsg + * \param sigmsg The message structure containing the variables + * \param data pointer to data + * \param datalen datalen length of data + * \retval FTDM_SUCCESS success, data was successfully saved + * \retval FTDM_FAIL failed, event already had data attached to it. + * \note data must have been allocated using ftdm_calloc, FreeTDM will free data once the usrmsg is processed. + */ +FT_DECLARE(ftdm_status_t) ftdm_sigmsg_set_raw_data(ftdm_sigmsg_t *sigmsg, void *data, ftdm_size_t datalen); /*! \brief Assert condition diff --git a/libs/freetdm/src/include/private/ftdm_state.h b/libs/freetdm/src/include/private/ftdm_state.h index 5672839d15..191f8aef82 100644 --- a/libs/freetdm/src/include/private/ftdm_state.h +++ b/libs/freetdm/src/include/private/ftdm_state.h @@ -188,7 +188,7 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_cancel_state(const char *file, const char * \note If this function is called with the wait parameter set to a non-zero value, the recursivity * of the channel lock must be == 1 because the channel will be unlocked/locked when waiting */ FT_DECLARE(ftdm_status_t) ftdm_channel_set_state(const char *file, const char *func, int line, - ftdm_channel_t *ftdmchan, ftdm_channel_state_t state, int wait); + ftdm_channel_t *ftdmchan, ftdm_channel_state_t state, int wait, ftdm_usrmsg_t *usrmsg); /*!\brief Set the state of a channel immediately and implicitly complete the previous state if needed * \note FTDM_SIGEVENT_INDICATION_COMPLETED will be sent if the state change @@ -207,7 +207,7 @@ FT_DECLARE(ftdm_status_t) _ftdm_set_state(const char *file, const char *func, in #define ftdm_set_state_locked(obj, s) \ do { \ ftdm_channel_lock(obj); \ - ftdm_channel_set_state(__FILE__, __FUNCTION__, __LINE__, obj, s, 0); \ + ftdm_channel_set_state(__FILE__, __FUNCTION__, __LINE__, obj, s, 0, NULL); \ ftdm_channel_unlock(obj); \ } while(0); diff --git a/libs/freetdm/src/include/private/ftdm_types.h b/libs/freetdm/src/include/private/ftdm_types.h old mode 100644 new mode 100755 index 9e8df1f5f2..b263b64a2d --- a/libs/freetdm/src/include/private/ftdm_types.h +++ b/libs/freetdm/src/include/private/ftdm_types.h @@ -203,6 +203,7 @@ typedef enum { FTDM_CHANNEL_FEATURE_HWEC = (1<<7), /*!< Channel has a hardware echo canceller */ FTDM_CHANNEL_FEATURE_HWEC_DISABLED_ON_IDLE = (1<<8), /*!< hardware echo canceller is disabled when there are no calls on this channel */ FTDM_CHANNEL_FEATURE_IO_STATS = (1<<9), /*!< Channel supports IO statistics (HDLC channels only) */ + FTDM_CHANNEL_FEATURE_MF_GENERATE = (1<<10), /*!< Channel can generate R2 MF tones (read-only) */ } ftdm_channel_feature_t; /*!< Channel flags. This used to be an enum but we reached the 32bit limit for enums, is safer this way */ diff --git a/libs/freetdm/src/testboost.c b/libs/freetdm/src/testboost.c deleted file mode 100644 index f55a46a11a..0000000000 --- a/libs/freetdm/src/testboost.c +++ /dev/null @@ -1,83 +0,0 @@ -#include "freetdm.h" -#include - -static FIO_SIGNAL_CB_FUNCTION(on_signal) -{ - return FTDM_FAIL; -} - -static int R = 0; -#if 0 -static void handle_SIGINT(int sig) -{ - if (sig); - R = 0; - return; -} -#endif -int main(int argc, char *argv[]) -{ - ftdm_conf_parameter_t parameters[20]; - ftdm_span_t *span; - int local_port, remote_port; - - local_port = remote_port = 53000; - - ftdm_global_set_default_logger(FTDM_LOG_LEVEL_DEBUG); -#if 0 - if (argc < 2) { - printf("invalid arguments\n"); - exit(-1); - } -#endif - - if (ftdm_global_init() != FTDM_SUCCESS) { - fprintf(stderr, "Error loading FreeTDM\n"); - exit(-1); - } - if (ftdm_global_configuration() != FTDM_SUCCESS) { - fprintf(stderr, "Error configuring FreeTDM\n"); - exit(-1); - } - - printf("FreeTDM loaded\n"); - - if (ftdm_span_find_by_name("wp1", &span) != FTDM_SUCCESS) { - fprintf(stderr, "Error finding FreeTDM span %s\n", argv[1]); - goto done; - } - parameters[0].var = "sigmod"; - parameters[0].val = "sangoma_prid"; - parameters[1].var = "switchtype"; - parameters[1].val = "euroisdn"; - parameters[1].var = "signalling"; - parameters[1].val = "pri_cpe"; - parameters[2].var = NULL; - if (ftdm_configure_span_signaling(span, "sangoma_boost", on_signal, parameters) == FTDM_SUCCESS) { - ftdm_span_start(span); - } else { - fprintf(stderr, "Error starting SS7_BOOST\n"); - goto done; - } - - while(ftdm_running() && R) { - ftdm_sleep(1 * 1000); - } - - done: - - ftdm_global_destroy(); - - return 0; -} - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4: - */ diff --git a/libs/freetdm/src/testsangomaboost.c b/libs/freetdm/src/testsangomaboost.c deleted file mode 100644 index b007fc186b..0000000000 --- a/libs/freetdm/src/testsangomaboost.c +++ /dev/null @@ -1,472 +0,0 @@ -/* - * Copyright (c) 2010, Sangoma Technologies - * Moises Silva - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * Sample program for the boost signaling absraction. - * Usage: boostsample - * The span name must be a valid span defined in freetdm.conf - * compile this program linking to the freetdm library (ie -lfreetdm) - **/ - -#ifndef __linux__ -#define _CRT_SECURE_NO_WARNINGS 1 -#endif - -#include - -#include -#include -#include - -#include "freetdm.h" - - -/* arbitrary limit for max calls in this sample program */ -#define MAX_CALLS 255 - -/* some timers (in seconds) to fake responses in incoming calls */ -#define PROGRESS_TIMER 1 -#define ANSWER_TIMER 5 -#define HANGUP_TIMER 15 - -/* simple variable used to stop the application */ -static int app_running = 0; - -typedef void (*expired_function_t)(ftdm_channel_t *channel); -typedef struct dummy_timer_s { - int time; - ftdm_channel_t *channel; - expired_function_t expired; -} dummy_timer_t; - -/* dummy second resolution timers */ -static dummy_timer_t g_timers[MAX_CALLS]; - -/* mutex to protect the timers (both, the test thread and the signaling thread may modify them) */ -static ftdm_mutex_t *g_schedule_mutex; - -/* mutex to protect the channel */ -static ftdm_mutex_t *g_channel_mutex; - -/* unique outgoing channel */ -static ftdm_channel_t *g_outgoing_channel = NULL; - -static void interrupt_requested(int signal) -{ - app_running = 0; -} - -static void schedule_timer(ftdm_channel_t *channel, int sec, expired_function_t expired) -{ - int i; - ftdm_mutex_lock(g_schedule_mutex); - for (i = 0; i < sizeof(g_timers)/sizeof(g_timers[0]); i++) { - /* check the timer slot is free to use */ - if (!g_timers[i].time) { - g_timers[i].time = sec; - g_timers[i].channel = channel; - g_timers[i].expired = expired; - ftdm_mutex_unlock(g_schedule_mutex); - return; - } - } - ftdm_log(FTDM_LOG_ERROR, "Failed to schedule timer\n"); - ftdm_mutex_unlock(g_schedule_mutex); -} - -static void run_timers(void) -{ - int i; - void *channel; - expired_function_t expired_func = NULL; - ftdm_mutex_lock(g_schedule_mutex); - for (i = 0; i < sizeof(g_timers)/sizeof(g_timers[0]); i++) { - /* if there's time left, decrement */ - if (g_timers[i].time) { - g_timers[i].time--; - } - - /* if time expired and we have an expired function, call it */ - if (!g_timers[i].time && g_timers[i].expired) { - expired_func = g_timers[i].expired; - channel = g_timers[i].channel; - memset(&g_timers[i], 0, sizeof(g_timers[i])); - expired_func(channel); - } - } - ftdm_mutex_unlock(g_schedule_mutex); -} - -static void release_timers(ftdm_channel_t *channel) -{ - int i; - ftdm_mutex_lock(g_schedule_mutex); - for (i = 0; i < sizeof(g_timers)/sizeof(g_timers[0]); i++) { - /* clear any timer belonging to the given channel */ - if (g_timers[i].channel == channel) { - memset(&g_timers[i], 0, sizeof(g_timers[i])); - } - } - ftdm_mutex_unlock(g_schedule_mutex); -} - -/* hangup the call */ -static void send_hangup(ftdm_channel_t *channel) -{ - char dtmfbuff[100]; - int rc; - int spanid = ftdm_channel_get_span_id(channel); - int chanid = ftdm_channel_get_id(channel); - rc = ftdm_channel_dequeue_dtmf(channel, dtmfbuff, sizeof(dtmfbuff)); - if (rc) { - ftdm_log(FTDM_LOG_NOTICE, "Not hanging up channel %d:%d because has DTMF: %s\n", spanid, chanid, dtmfbuff); - schedule_timer(channel, HANGUP_TIMER, send_hangup); - return; - } - ftdm_log(FTDM_LOG_NOTICE, "-- Requesting hangup in channel %d:%d\n", spanid, chanid); - ftdm_channel_call_hangup(channel); -} - -/* send answer for an incoming call */ -static void send_answer(ftdm_channel_t *channel) -{ - /* we move the channel signaling state machine to UP (answered) */ - int spanid = ftdm_channel_get_span_id(channel); - int chanid = ftdm_channel_get_id(channel); - ftdm_log(FTDM_LOG_NOTICE, "-- Requesting answer in channel %d:%d\n", spanid, chanid); - ftdm_channel_call_answer(channel); - schedule_timer(channel, HANGUP_TIMER, send_hangup); -} - -/* send progress for an incoming */ -static void send_progress(ftdm_channel_t *channel) -{ - /* we move the channel signaling state machine to UP (answered) */ - int spanid = ftdm_channel_get_span_id(channel); - int chanid = ftdm_channel_get_id(channel); - ftdm_log(FTDM_LOG_NOTICE, "-- Requesting progress\n", spanid, chanid); - ftdm_channel_call_indicate(channel, FTDM_CHANNEL_INDICATE_PROGRESS); - schedule_timer(channel, ANSWER_TIMER, send_answer); -} - -/* This function will be called in an undetermined signaling thread, you must not do - * any blocking operations here or the signaling stack may delay other call event processing - * The arguments for this function are defined in FIO_SIGNAL_CB_FUNCTION prototype, I just - * name them here for your convenience: - * ftdm_sigmsg_t *sigmsg - * - The sigmsg structure contains the ftdm_channel structure that represents the channel where - * the event occurred and the event_id of the signaling event that just occurred. - * */ -static FIO_SIGNAL_CB_FUNCTION(on_signaling_event) -{ - switch (sigmsg->event_id) { - /* This event signals the start of an incoming call */ - case FTDM_SIGEVENT_START: - ftdm_log(FTDM_LOG_NOTICE, "Incoming call received in channel %d:%d\n", sigmsg->span_id, sigmsg->chan_id); - schedule_timer(sigmsg->channel, PROGRESS_TIMER, send_progress); - break; - /* This event signals progress on an outgoing call */ - case FTDM_SIGEVENT_PROGRESS_MEDIA: - ftdm_log(FTDM_LOG_NOTICE, "Progress message received in channel %d:%d\n", sigmsg->span_id, sigmsg->chan_id); - break; - /* This event signals answer in an outgoing call */ - case FTDM_SIGEVENT_UP: - ftdm_log(FTDM_LOG_NOTICE, "Answer received in channel %d:%d\n", sigmsg->span_id, sigmsg->chan_id); - ftdm_channel_command(sigmsg->channel, FTDM_COMMAND_ENABLE_DTMF_DETECT, NULL); - /* now the channel is answered and we can use - * ftdm_channel_wait() to wait for input/output in a channel (equivalent to poll() or select()) - * ftdm_channel_read() to read available data in a channel - * ftdm_channel_write() to write to the channel */ - break; - /* This event signals hangup from the other end */ - case FTDM_SIGEVENT_STOP: - ftdm_log(FTDM_LOG_NOTICE, "Hangup received in channel %d:%d\n", sigmsg->span_id, sigmsg->chan_id); - ftdm_mutex_lock(g_channel_mutex); - if (g_outgoing_channel == sigmsg->channel) { - g_outgoing_channel = NULL; - } - ftdm_mutex_unlock(g_channel_mutex); - /* release any timer for this channel */ - release_timers(sigmsg->channel); - /* acknowledge the hangup */ - ftdm_channel_call_hangup(sigmsg->channel); - break; - default: - ftdm_log(FTDM_LOG_WARNING, "Unhandled event %s in channel %d:%d\n", ftdm_signal_event2str(sigmsg->event_id), - sigmsg->span_id, sigmsg->chan_id); - break; - } - return FTDM_SUCCESS; -} - -static void place_call(const ftdm_span_t *span, const char *number) -{ - ftdm_channel_t *ftdmchan = NULL; - ftdm_caller_data_t caller_data = {{ 0 }}; - ftdm_status_t status = FTDM_FAIL; - - /* set destiny number */ - ftdm_set_string(caller_data.dnis.digits, number); - - /* set callerid */ - ftdm_set_string(caller_data.cid_name, "testsangomaboost"); - ftdm_set_string(caller_data.cid_num.digits, "1234"); - - /* request to search for an outgoing channel top down with the given caller data. - * it is also an option to use ftdm_channel_open_by_group to let freetdm hunt - * an available channel in a given group instead of per span - * */ - status = ftdm_channel_open_by_span(ftdm_span_get_id(span), FTDM_TOP_DOWN, &caller_data, &ftdmchan); - if (status != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "Failed to originate call\n"); - return; - } - - ftdm_mutex_lock(g_channel_mutex); - g_outgoing_channel = ftdmchan; - ftdm_mutex_unlock(g_channel_mutex); - - /* set the caller data for the outgoing channel */ - ftdm_channel_set_caller_data(ftdmchan, &caller_data); - - status = ftdm_channel_call_place(ftdmchan); - if (status != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "Failed to originate call\n"); - return; - } - - /* this is required to initialize the outgoing channel */ - ftdm_channel_init(ftdmchan); -} - -static void *media_thread(ftdm_thread_t *th, void *data) -{ - /* The application thread can go on and do anything else, like waiting for a shutdown signal */ - ftdm_wait_flag_t flags = FTDM_NO_FLAGS; - ftdm_status_t status; - ftdm_channel_t *chan; - char iobuff[160]; - char dnis_str[] = "1234"; - int tx_dtmf = 0; - ftdm_size_t datalen = 0; - memset(iobuff, 0, sizeof(iobuff)); - while(ftdm_running() && app_running) { - ftdm_mutex_lock(g_channel_mutex); - chan = g_outgoing_channel; - ftdm_mutex_unlock(g_channel_mutex); - if (chan && tx_dtmf) { - flags = FTDM_WRITE | FTDM_READ; - ftdm_channel_wait(chan, &flags, 100); - if (flags & FTDM_WRITE) { - datalen = sizeof(iobuff); - status = ftdm_channel_write(chan, iobuff, datalen, &datalen); - if (status != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "writing to channel failed\n"); - } - } - if (flags & FTDM_READ) { - datalen = sizeof(iobuff); - status = ftdm_channel_read(chan, iobuff, &datalen); - if (status != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "reading from channel failed\n"); - } - } - } else if (chan && ftdm_channel_call_check_answered(chan)) { - ftdm_log(FTDM_LOG_NOTICE, "Transmitting DNIS %s\n", dnis_str); - ftdm_channel_command(g_outgoing_channel, FTDM_COMMAND_SEND_DTMF, dnis_str); - tx_dtmf = 1; - } else { - tx_dtmf = 0; - ftdm_sleep(100); - } - } - printf("Shutting down media thread ...\n"); - return NULL; -} - -int main(int argc, char *argv[]) -{ - ftdm_conf_parameter_t parameters[20]; - ftdm_span_t *span; - char *todial = NULL; - const char *sigtype = NULL; - int32_t ticks = 0; - - if (argc < 3) { - fprintf(stderr, "Usage: %s [number to dial if any]\n", argv[0]); - exit(-1); - } - - /* register a handler to shutdown things properly */ -#ifdef _WIN64 - // still trying to figure this one out otherwise triggers error - if (signal(SIGINT, interrupt_requested) < 0) { -#else - if (signal(SIGINT, interrupt_requested) == SIG_ERR) { -#endif - fprintf(stderr, "Could not set the SIGINT signal handler: %s\n", strerror(errno)); - exit(-1); - } - - if (!strcmp(argv[2], "cpe")) { - sigtype = "pri_cpe"; - } else if (!strcmp(argv[2], "net")) { - sigtype = "pri_net"; - } else { - fprintf(stderr, "Valid signaling types are cpe and net only\n"); - exit(-1); - } - printf("Using signalling %s\n", sigtype); - - if (argc >= 4) { - todial = argv[3]; - if (!strlen(todial)) { - todial = NULL; - } - } - - /* clear any outstanding timers */ - memset(&g_timers, 0, sizeof(g_timers)); - - /* set the logging level to use */ - ftdm_global_set_default_logger(FTDM_LOG_LEVEL_DEBUG); - - /* Initialize the FTDM library */ - if (ftdm_global_init() != FTDM_SUCCESS) { - fprintf(stderr, "Error loading FreeTDM\n"); - exit(-1); - } - - /* create the schedule and channel mutex */ - ftdm_mutex_create(&g_schedule_mutex); - ftdm_mutex_create(&g_channel_mutex); - - /* Load the FreeTDM configuration */ - if (ftdm_global_configuration() != FTDM_SUCCESS) { - fprintf(stderr, "Error configuring FreeTDM\n"); - exit(-1); - } - - /* At this point FreeTDM is ready to be used, the spans defined in freetdm.conf have the basic I/O board configuration - * but no telephony signaling configuration at all. */ - printf("FreeTDM loaded ...\n"); - - /* Retrieve a span by name (according to freetdm.conf) */ - if (ftdm_span_find_by_name(argv[1], &span) != FTDM_SUCCESS) { - fprintf(stderr, "Error finding FreeTDM span %s\n", argv[1]); - goto done; - } - - /* prepare the configuration parameters that will be sent down to the signaling stack, the array of paramters must be terminated by an - * array element with a null .var member */ - - /* for sangoma_boost signaling (abstraction signaling used by Sangoma for PRI, BRI and SS7) the first parameter you must send - * is sigmod, which must be either sangoma_prid, if you have the PRI stack available, or sangoma_brid for the BRI stack */ - parameters[0].var = "sigmod"; - parameters[0].val = "sangoma_prid"; - - /* following parameters are signaling stack specific, this ones are for PRI */ - parameters[1].var = "switchtype"; - parameters[1].val = "national"; - - parameters[2].var = "signalling"; - parameters[2].val = sigtype; - - /* - * parameters[3].var = "nfas_primary"; - * parameters[3].val = "4"; //span number - * - * parameters[4].var = "nfas_secondary"; - * parameters[4].val = "2"; //span number - * - * parameters[5].var = "nfas_group"; - * parameters[5].val = "1"; - * */ - - /* the last parameter .var member must be NULL! */ - parameters[3].var = NULL; - - /* send the configuration values down to the stack */ - if (ftdm_configure_span_signaling(span, "sangoma_boost", on_signaling_event, parameters) != FTDM_SUCCESS) { - fprintf(stderr, "Error configuring sangoma_boost signaling abstraction in span %s\n", ftdm_span_get_name(span)); - goto done; - } - - /* configuration succeeded, we can proceed now to start the span - * This step will launch at least 1 background (may be more, depending on the signaling stack used) - * to handle *ALL* signaling events for this span, your on_signaling_event callback will be called always - * in one of those infraestructure threads and you MUST NOT block in that handler to avoid delays and errors - * in the signaling processing for any call. - * */ - ftdm_span_start(span); - - if (ftdm_thread_create_detached(media_thread, NULL) != FTDM_SUCCESS){ - fprintf(stderr, "Error launching media thread\n"); - goto done; - } - - app_running = 1; - - /* The application thread can go on and do anything else, like waiting for a shutdown signal */ - while(ftdm_running() && app_running) { - ftdm_sleep(1000); - run_timers(); - ticks++; - if (!(ticks % 10) && todial && !g_outgoing_channel) { - ftdm_log(FTDM_LOG_NOTICE, "Originating call to number %s\n", todial); - place_call(span, todial); - } - } - printf("Shutting down FreeTDM ...\n"); - done: - - ftdm_mutex_destroy(&g_schedule_mutex); - ftdm_mutex_destroy(&g_channel_mutex); - - /* whenever you're done, this function will shutdown the signaling threads in any span that was started */ - ftdm_global_destroy(); - - return 0; -} - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4: - */ diff --git a/libs/stfu/stfu.c b/libs/stfu/stfu.c index d2c443a9e7..f00dfafa39 100644 --- a/libs/stfu/stfu.c +++ b/libs/stfu/stfu.c @@ -102,7 +102,10 @@ struct stfu_instance { int32_t ts_offset; int32_t ts_drift; - + int32_t max_drift; + uint32_t drift_dropped_packets; + uint32_t drift_max_dropped; + int32_t ts_diff; int32_t last_ts_diff; int32_t same_ts; @@ -258,7 +261,7 @@ stfu_status_t stfu_n_resize(stfu_instance_t *i, uint32_t qlen) return s; } -stfu_instance_t *stfu_n_init(uint32_t qlen, uint32_t max_qlen, uint32_t samples_per_packet, uint32_t samples_per_second) +stfu_instance_t *stfu_n_init(uint32_t qlen, uint32_t max_qlen, uint32_t samples_per_packet, uint32_t samples_per_second, uint32_t max_drift_ms) { struct stfu_instance *i; @@ -277,6 +280,12 @@ stfu_instance_t *stfu_n_init(uint32_t qlen, uint32_t max_qlen, uint32_t samples_ stfu_n_init_aqueue(&i->b_queue, qlen); stfu_n_init_aqueue(&i->c_queue, qlen); + i->max_drift = (int32_t)(max_drift_ms * (samples_per_second / 1000) * -1); + + if (max_drift_ms && samples_per_packet) { + i->drift_max_dropped = (samples_per_second * 2) / samples_per_packet; + } + i->in_queue = &i->a_queue; i->out_queue = &i->b_queue; i->old_queue = &i->c_queue; @@ -396,6 +405,9 @@ stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t pt, void if (i->last_ts_diff == i->ts_diff) { if (++i->same_ts == 5) { i->samples_per_packet = i->ts_diff; + if (i->max_drift && i->samples_per_packet) { + i->drift_max_dropped = (i->samples_per_second * 2) / i->samples_per_packet; + } } } else { i->same_ts = 0; @@ -409,11 +421,24 @@ stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t pt, void } } - if (timer_ts && ts && !i->ts_offset) { - i->ts_offset = timer_ts - ts; - } + if (timer_ts) { + if (ts && !i->ts_offset) { + i->ts_offset = timer_ts - ts; + } - i->ts_drift = ts + (i->ts_offset - timer_ts); + i->ts_drift = ts + (i->ts_offset - timer_ts); + + if (i->max_drift) { + if (i->ts_drift < i->max_drift) { + if (++i->drift_dropped_packets < i->drift_max_dropped) { + stfu_log(STFU_LOG_EMERG, "%s TOO LATE !!! %u \n\n\n", i->name, ts); + return STFU_ITS_TOO_LATE; + } + } else { + i->drift_dropped_packets = 0; + } + } + } if (i->sync_in) { good_ts = 1; @@ -493,12 +518,12 @@ stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t pt, void if (stfu_log != null_logger && i->debug) { - stfu_log(STFU_LOG_EMERG, "I: %s %u i=%u/%u - g:%u/%u c:%u/%u b:%u - %u:%u - %u %d %u %u %d %d %d\n", i->name, + stfu_log(STFU_LOG_EMERG, "I: %s %u i=%u/%u - g:%u/%u c:%u/%u b:%u - %u:%u - %u %d %u %u %d %d %d/%d\n", i->name, i->qlen, i->period_packet_in_count, i->period_time, i->consecutive_good_count, i->decrement_time, i->period_clean_count, i->decrement_time, i->consecutive_bad_count, ts, ts / i->samples_per_packet, i->period_missing_count, i->period_need_range_avg, - i->last_wr_ts, ts, i->diff, i->diff_total / least1(i->period_packet_in_count), i->ts_drift); + i->last_wr_ts, ts, i->diff, i->diff_total / least1(i->period_packet_in_count), i->ts_drift, i->max_drift); } if (last || i->in_queue->array_len == i->in_queue->array_size) { @@ -597,7 +622,7 @@ stfu_frame_t *stfu_n_read_a_frame(stfu_instance_t *i) if (!i->ready) { if (stfu_log != null_logger && i->debug) { - stfu_log(STFU_LOG_EMERG, "%s XXXSKIP\n", i->name); + stfu_log(STFU_LOG_EMERG, "%s JITTERBUFFER NOT READY: IGNORING FRAME\n", i->name); } return NULL; } @@ -612,7 +637,7 @@ stfu_frame_t *stfu_n_read_a_frame(stfu_instance_t *i) } if (i->cur_ts == 0) { if (stfu_log != null_logger && i->debug) { - stfu_log(STFU_LOG_EMERG, "%s XXXPUNT\n", i->name); + stfu_log(STFU_LOG_EMERG, "%s JITTERBUFFER ERROR: PUNTING\n", i->name); return NULL; } } diff --git a/libs/stfu/stfu.h b/libs/stfu/stfu.h index b92bb3f839..d8fbf447af 100644 --- a/libs/stfu/stfu.h +++ b/libs/stfu/stfu.h @@ -179,7 +179,7 @@ typedef void (*stfu_n_call_me_t)(stfu_instance_t *i, void *); void stfu_n_report(stfu_instance_t *i, stfu_report_t *r); void stfu_n_destroy(stfu_instance_t **i); -stfu_instance_t *stfu_n_init(uint32_t qlen, uint32_t max_qlen, uint32_t samples_per_packet, uint32_t samples_per_second); +stfu_instance_t *stfu_n_init(uint32_t qlen, uint32_t max_qlen, uint32_t samples_per_packet, uint32_t samples_per_second, uint32_t max_drift_ms); stfu_status_t stfu_n_resize(stfu_instance_t *i, uint32_t qlen); stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t pt, void *data, size_t datalen, uint32_t timer_ts, int last); stfu_frame_t *stfu_n_read_a_frame(stfu_instance_t *i); diff --git a/src/include/private/switch_core_pvt.h b/src/include/private/switch_core_pvt.h index ab0777ed3b..0ef64d1079 100644 --- a/src/include/private/switch_core_pvt.h +++ b/src/include/private/switch_core_pvt.h @@ -249,6 +249,8 @@ struct switch_runtime { switch_dbtype_t odbc_dbtype; char hostname[256]; int multiple_registrations; + uint32_t max_db_handles; + uint32_t db_handle_timeout; }; extern struct switch_runtime runtime; diff --git a/src/include/switch_channel.h b/src/include/switch_channel.h index c0bef4be59..25273bafc4 100644 --- a/src/include/switch_channel.h +++ b/src/include/switch_channel.h @@ -79,6 +79,7 @@ SWITCH_DECLARE(int) switch_channel_test_ready(switch_channel_t *channel, switch_ #define switch_channel_ready(_channel) switch_channel_test_ready(_channel, SWITCH_TRUE, SWITCH_FALSE) #define switch_channel_media_ready(_channel) switch_channel_test_ready(_channel, SWITCH_TRUE, SWITCH_TRUE) +#define switch_channel_media_up(_channel) (switch_channel_test_flag(_channel, CF_ANSWERED) || switch_channel_test_flag(_channel, CF_EARLY_MEDIA)) #define switch_channel_up(_channel) (switch_channel_get_state(_channel) < CS_HANGUP) #define switch_channel_down(_channel) (switch_channel_get_state(_channel) >= CS_HANGUP) diff --git a/src/include/switch_core.h b/src/include/switch_core.h index 984b54fac7..590e01ace2 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -2075,52 +2075,40 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_preprocess_session(switch_core_sessio */ #define CACHE_DB_LEN 256 - typedef enum { - CDF_INUSE = (1 << 0), - CDF_PRUNE = (1 << 1) - } cache_db_flag_t; +typedef enum { + CDF_INUSE = (1 << 0), + CDF_PRUNE = (1 << 1) +} cache_db_flag_t; - typedef enum { - SCDB_TYPE_CORE_DB, - SCDB_TYPE_ODBC - } switch_cache_db_handle_type_t; +typedef enum { + SCDB_TYPE_CORE_DB, + SCDB_TYPE_ODBC +} switch_cache_db_handle_type_t; - typedef union { - switch_core_db_t *core_db_dbh; - switch_odbc_handle_t *odbc_dbh; - } switch_cache_db_native_handle_t; +typedef union { + switch_core_db_t *core_db_dbh; + switch_odbc_handle_t *odbc_dbh; +} switch_cache_db_native_handle_t; - typedef struct { - char *db_path; - } switch_cache_db_core_db_options_t; +typedef struct { + char *db_path; +} switch_cache_db_core_db_options_t; - typedef struct { - char *dsn; - char *user; - char *pass; - } switch_cache_db_odbc_options_t; +typedef struct { + char *dsn; + char *user; + char *pass; +} switch_cache_db_odbc_options_t; - typedef union { - switch_cache_db_core_db_options_t core_db_options; - switch_cache_db_odbc_options_t odbc_options; - } switch_cache_db_connection_options_t; +typedef union { + switch_cache_db_core_db_options_t core_db_options; + switch_cache_db_odbc_options_t odbc_options; +} switch_cache_db_connection_options_t; - typedef struct { - char name[CACHE_DB_LEN]; - switch_cache_db_handle_type_t type; - switch_cache_db_native_handle_t native_handle; - time_t last_used; - switch_mutex_t *mutex; - switch_mutex_t *io_mutex; - switch_memory_pool_t *pool; - int32_t flags; - unsigned long hash; - char creator[CACHE_DB_LEN]; - char last_user[CACHE_DB_LEN]; - } switch_cache_db_handle_t; +struct switch_cache_db_handle; +typedef struct switch_cache_db_handle switch_cache_db_handle_t; - - static inline const char *switch_cache_db_type_name(switch_cache_db_handle_type_t type) +static inline const char *switch_cache_db_type_name(switch_cache_db_handle_type_t type) { const char *type_str = "INVALID"; @@ -2140,6 +2128,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_preprocess_session(switch_core_sessio return type_str; } +SWITCH_DECLARE(switch_cache_db_handle_type_t) switch_cache_db_get_type(switch_cache_db_handle_t *dbh); + /*! \brief Returns the handle to the pool, immediately available for other threads to use. @@ -2152,11 +2142,6 @@ SWITCH_DECLARE(void) switch_cache_db_dismiss_db_handle(switch_cache_db_handle_t \param [in] The handle */ SWITCH_DECLARE(void) switch_cache_db_release_db_handle(switch_cache_db_handle_t ** dbh); -/*! - \brief Removes the handle from the pool and frees up the handle resources. - \param [in] The handle -*/ -SWITCH_DECLARE(void) switch_cache_db_destroy_db_handle(switch_cache_db_handle_t ** dbh); /*! \brief Gets a new cached handle from the pool, potentially creating a new connection. The connection is bound to the thread until it (the thread) terminates unless @@ -2217,19 +2202,40 @@ SWITCH_DECLARE(switch_bool_t) switch_cache_db_test_reactive(switch_cache_db_hand const char *test_sql, const char *drop_sql, const char *reactive_sql); SWITCH_DECLARE(switch_status_t) switch_cache_db_persistant_execute(switch_cache_db_handle_t *dbh, const char *sql, uint32_t retries); SWITCH_DECLARE(switch_status_t) switch_cache_db_persistant_execute_trans(switch_cache_db_handle_t *dbh, char *sql, uint32_t retries); -/*! - \brief Tries to detach all free connections from current thread. -*/ -SWITCH_DECLARE(void) switch_cache_db_detach(void); + SWITCH_DECLARE(uint32_t) switch_core_debug_level(void); SWITCH_DECLARE(void) switch_cache_db_flush_handles(void); SWITCH_DECLARE(const char *) switch_core_banner(void); SWITCH_DECLARE(switch_bool_t) switch_core_session_in_thread(switch_core_session_t *session); SWITCH_DECLARE(uint32_t) switch_default_ptime(const char *name, uint32_t number); +/*! + \brief Add user registration + \param [in] user + \param [in] realm + \param [in] token + \param [in] url - a freeswitch dial string + \param [in] expires + \param [in] network_ip + \param [in] network_port + \param [in] network_proto - one of tls, tcp, udp + \param [out] err - Error if it exists +*/ SWITCH_DECLARE(switch_status_t) switch_core_add_registration(const char *user, const char *realm, const char *token, const char *url, uint32_t expires, const char *network_ip, const char *network_port, const char *network_proto); +/*! + \brief Delete user registration + \param [in] user + \param [in] realm + \param [in] token + \param [out] err - Error if it exists +*/ SWITCH_DECLARE(switch_status_t) switch_core_del_registration(const char *user, const char *realm, const char *token); +/*! + \brief Expire user registrations + \param [in] force delete all registrations + \param [out] err - Error if it exists +*/ SWITCH_DECLARE(switch_status_t) switch_core_expire_registration(int force); SWITCH_END_EXTERN_C diff --git a/src/include/switch_resample.h b/src/include/switch_resample.h index b38e094dd6..3dff620c4b 100644 --- a/src/include/switch_resample.h +++ b/src/include/switch_resample.h @@ -39,6 +39,7 @@ */ #define switch_normalize_volume(x) if (x > 4) x = 4; if (x < -4) x = -4; +#define switch_normalize_volume_granular(x) if (x > 12) x = 12; if (x < -12) x = -12; #ifndef SWITCH_RESAMPLE_H #define SWITCH_RESAMPLE_H @@ -158,6 +159,14 @@ SWITCH_DECLARE(void) switch_generate_sln_silence(int16_t *data, uint32_t samples \param vol the volume factor -4 -> 4 */ SWITCH_DECLARE(void) switch_change_sln_volume(int16_t *data, uint32_t samples, int32_t vol); + +/*! + \brief Change the volume of a signed linear audio frame with more granularity + \param data the audio data + \param samples the number of 2 byte samples + \param vol the volume factor -12 -> 12 + */ +SWITCH_DECLARE(void) switch_change_sln_volume_granular(int16_t *data, uint32_t samples, int32_t vol); ///\} SWITCH_DECLARE(uint32_t) switch_merge_sln(int16_t *data, uint32_t samples, int16_t *other_data, uint32_t other_samples); diff --git a/src/include/switch_rtp.h b/src/include/switch_rtp.h index 2870bba3af..94c9d671e9 100644 --- a/src/include/switch_rtp.h +++ b/src/include/switch_rtp.h @@ -232,7 +232,7 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_activate_rtcp(switch_rtp_t *rtp_sessi SWITCH_DECLARE(switch_status_t) switch_rtp_activate_jitter_buffer(switch_rtp_t *rtp_session, uint32_t queue_frames, uint32_t max_queue_frames, - uint32_t samples_per_packet, uint32_t samples_per_second); + uint32_t samples_per_packet, uint32_t samples_per_second, uint32_t max_drift); SWITCH_DECLARE(switch_status_t) switch_rtp_debug_jitter_buffer(switch_rtp_t *rtp_session, const char *name); diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 3972404290..4253d0e542 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -1504,6 +1504,8 @@ typedef enum { SWITCH_EVENT_NAT, SWITCH_EVENT_RECORD_START, SWITCH_EVENT_RECORD_STOP, + SWITCH_EVENT_PLAYBACK_START, + SWITCH_EVENT_PLAYBACK_STOP, SWITCH_EVENT_CALL_UPDATE, SWITCH_EVENT_FAILURE, SWITCH_EVENT_SOCKET_DATA, diff --git a/src/include/switch_utils.h b/src/include/switch_utils.h index a1a93c6ac8..7fcb1e8c75 100644 --- a/src/include/switch_utils.h +++ b/src/include/switch_utils.h @@ -189,10 +189,12 @@ static inline char switch_itodtmf(char i) char r = i; if (i > 9 && i < 14) { - r = i + 55; + r += 55; + } else { + r += 48; } - return r + 48; + return r; } static inline int switch_dtmftoi(char *s) diff --git a/src/mod/applications/mod_callcenter/mod_callcenter.c b/src/mod/applications/mod_callcenter/mod_callcenter.c index 9d9feed0aa..12e1960841 100644 --- a/src/mod/applications/mod_callcenter/mod_callcenter.c +++ b/src/mod/applications/mod_callcenter/mod_callcenter.c @@ -1223,7 +1223,7 @@ static switch_status_t load_agent(const char *agent_name) cc_agent_update("reject_delay_time", reject_delay_time, agent_name); } if (busy_delay_time) { - cc_agent_update("busy_delay_time", reject_delay_time, agent_name); + cc_agent_update("busy_delay_time", busy_delay_time, agent_name); } if (type && res == CC_STATUS_AGENT_ALREADY_EXIST) { diff --git a/src/mod/applications/mod_commands/mod_commands.c b/src/mod/applications/mod_commands/mod_commands.c index 517134d2e1..a6df087cb0 100644 --- a/src/mod/applications/mod_commands/mod_commands.c +++ b/src/mod/applications/mod_commands/mod_commands.c @@ -90,11 +90,11 @@ static switch_status_t select_url(const char *user, if (exclude_contact) { sql = switch_mprintf("select url, '%q' " - "from registrations where user='%q' and realm='%q' " + "from registrations where reg_user='%q' and realm='%q' " "and url not like '%%%s%%'", (concat != NULL) ? concat : "", user, domain, exclude_contact); } else { sql = switch_mprintf("select url, '%q' " - "from registrations where user='%q' and realm='%q'", + "from registrations where reg_user='%q' and realm='%q'", (concat != NULL) ? concat : "", user, domain); } diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c index 5eeae5c781..d0f5fac081 100644 --- a/src/mod/applications/mod_conference/mod_conference.c +++ b/src/mod/applications/mod_conference/mod_conference.c @@ -36,7 +36,8 @@ * */ #include -//#define INTENSE_DEBUG +#define DEFAULT_AGC_LEVEL 1100 + SWITCH_MODULE_LOAD_FUNCTION(mod_conference_load); SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_conference_shutdown); SWITCH_MODULE_DEFINITION(mod_conference, mod_conference_load, mod_conference_shutdown, NULL); @@ -194,7 +195,8 @@ typedef enum { EFLAG_BGDIAL_RESULT = (1 << 24), EFLAG_FLOOR_CHANGE = (1 << 25), EFLAG_MUTE_DETECT = (1 << 26), - EFLAG_RECORD = (1 << 27) + EFLAG_RECORD = (1 << 27), + EFLAG_AUTO_GAIN_LEVEL = (1 << 28) } event_type_t; typedef struct conference_file_node { @@ -266,7 +268,6 @@ typedef struct conference_obj { switch_thread_rwlock_t *rwlock; uint32_t count; int32_t energy_level; - int32_t agc_energy_level; uint8_t min; switch_speech_handle_t lsh; switch_speech_handle_t *sh; @@ -312,12 +313,15 @@ struct conference_member { switch_buffer_t *resample_buffer; uint32_t flags; uint32_t score; + uint32_t last_score; uint32_t score_iir; switch_mutex_t *flag_mutex; switch_mutex_t *write_mutex; switch_mutex_t *audio_in_mutex; switch_mutex_t *audio_out_mutex; switch_mutex_t *read_mutex; + switch_thread_rwlock_t *rwlock; + switch_codec_implementation_t read_impl; switch_codec_implementation_t orig_read_impl; switch_codec_t read_codec; switch_codec_t write_codec; @@ -372,6 +376,7 @@ typedef struct api_command { char *pname; void_fn_t pfnapicmd; conference_fntype_t fntype; + char *pcommand; char *psyntax; } api_command_t; @@ -559,6 +564,7 @@ static conference_member_t *conference_member_get(conference_obj_t *conference, member = NULL; } + switch_thread_rwlock_rdlock(member->rwlock); switch_mutex_unlock(conference->member_mutex); return member; @@ -803,6 +809,8 @@ static switch_status_t conference_del_member(conference_obj_t *conference, confe switch_assert(conference != NULL); switch_assert(member != NULL); + switch_thread_rwlock_wrlock(member->rwlock); + lock_member(member); member_fnode = member->fnode; member_sh = member->sh; @@ -831,6 +839,8 @@ static switch_status_t conference_del_member(conference_obj_t *conference, confe last = imember; } + switch_thread_rwlock_unlock(member->rwlock); + /* Close Unused Handles */ if (member_fnode) { conference_file_node_t *fnode, *cur; @@ -1595,16 +1605,17 @@ static void conference_loop_fn_deafmute_toggle(conference_member_t *member, call static void conference_loop_fn_energy_up(conference_member_t *member, caller_control_action_t *action) { - char msg[512]; + char msg[512], str[30] = ""; switch_event_t *event; + char *p; if (member == NULL) return; lock_member(member); member->energy_level += 200; - if (member->energy_level > 3000) { - member->energy_level = 3000; + if (member->energy_level > 1800) { + member->energy_level = 1800; } if (test_eflag(member->conference, EFLAG_ENERGY_LEVEL) && @@ -1616,13 +1627,23 @@ static void conference_loop_fn_energy_up(conference_member_t *member, caller_con } unlock_member(member); - switch_snprintf(msg, sizeof(msg), "Energy level %d", member->energy_level); - conference_member_say(member, msg, 0); + //switch_snprintf(msg, sizeof(msg), "Energy level %d", member->energy_level); + //conference_member_say(member, msg, 0); + + switch_snprintf(str, sizeof(str), "%d", abs(member->energy_level) / 200); + for (p = str; p && *p; p++) { + switch_snprintf(msg, sizeof(msg), "digits/%c.wav", *p); + conference_member_play_file(member, msg, 0); + } + + + + } static void conference_loop_fn_energy_equ_conf(conference_member_t *member, caller_control_action_t *action) { - char msg[512]; + char msg[512], str[30] = "", *p; switch_event_t *event; if (member == NULL) @@ -1640,20 +1661,27 @@ static void conference_loop_fn_energy_equ_conf(conference_member_t *member, call } unlock_member(member); - switch_snprintf(msg, sizeof(msg), "Energy level %d", member->energy_level); - conference_member_say(member, msg, 0); + //switch_snprintf(msg, sizeof(msg), "Energy level %d", member->energy_level); + //conference_member_say(member, msg, 0); + + switch_snprintf(str, sizeof(str), "%d", abs(member->energy_level) / 200); + for (p = str; p && *p; p++) { + switch_snprintf(msg, sizeof(msg), "digits/%c.wav", *p); + conference_member_play_file(member, msg, 0); + } + } static void conference_loop_fn_energy_dn(conference_member_t *member, caller_control_action_t *action) { - char msg[512]; + char msg[512], str[30] = "", *p; switch_event_t *event; if (member == NULL) return; lock_member(member); - member->energy_level -= 100; + member->energy_level -= 200; if (member->energy_level < 0) { member->energy_level = 0; } @@ -1667,8 +1695,15 @@ static void conference_loop_fn_energy_dn(conference_member_t *member, caller_con } unlock_member(member); - switch_snprintf(msg, sizeof(msg), "Energy level %d", member->energy_level); - conference_member_say(member, msg, 0); + //switch_snprintf(msg, sizeof(msg), "Energy level %d", member->energy_level); + //conference_member_say(member, msg, 0); + + switch_snprintf(str, sizeof(str), "%d", abs(member->energy_level) / 200); + for (p = str; p && *p; p++) { + switch_snprintf(msg, sizeof(msg), "digits/%c.wav", *p); + conference_member_play_file(member, msg, 0); + } + } static void conference_loop_fn_volume_talk_up(conference_member_t *member, caller_control_action_t *action) @@ -1692,8 +1727,17 @@ static void conference_loop_fn_volume_talk_up(conference_member_t *member, calle } unlock_member(member); - switch_snprintf(msg, sizeof(msg), "Volume level %d", member->volume_out_level); - conference_member_say(member, msg, 0); + //switch_snprintf(msg, sizeof(msg), "Volume level %d", member->volume_out_level); + //conference_member_say(member, msg, 0); + + if (member->volume_out_level < 0) { + switch_snprintf(msg, sizeof(msg), "currency/negative.wav", member->volume_out_level); + conference_member_play_file(member, msg, 0); + } + + switch_snprintf(msg, sizeof(msg), "digits/%d.wav", abs(member->volume_out_level)); + conference_member_play_file(member, msg, 0); + } static void conference_loop_fn_volume_talk_zero(conference_member_t *member, caller_control_action_t *action) @@ -1716,9 +1760,17 @@ static void conference_loop_fn_volume_talk_zero(conference_member_t *member, cal } unlock_member(member); - switch_snprintf(msg, sizeof(msg), "Volume level %d", member->volume_out_level); - conference_member_say(member, msg, 0); + //switch_snprintf(msg, sizeof(msg), "Volume level %d", member->volume_out_level); + //conference_member_say(member, msg, 0); + + if (member->volume_out_level < 0) { + switch_snprintf(msg, sizeof(msg), "currency/negative.wav", member->volume_out_level); + conference_member_play_file(member, msg, 0); + } + + switch_snprintf(msg, sizeof(msg), "digits/%d.wav", abs(member->volume_out_level)); + conference_member_play_file(member, msg, 0); } static void conference_loop_fn_volume_talk_dn(conference_member_t *member, caller_control_action_t *action) @@ -1742,8 +1794,16 @@ static void conference_loop_fn_volume_talk_dn(conference_member_t *member, calle } unlock_member(member); - switch_snprintf(msg, sizeof(msg), "Volume level %d", member->volume_out_level); - conference_member_say(member, msg, 0); + //switch_snprintf(msg, sizeof(msg), "Volume level %d", member->volume_out_level); + //conference_member_say(member, msg, 0); + + if (member->volume_out_level < 0) { + switch_snprintf(msg, sizeof(msg), "currency/negative.wav", member->volume_out_level); + conference_member_play_file(member, msg, 0); + } + + switch_snprintf(msg, sizeof(msg), "digits/%d.wav", abs(member->volume_out_level)); + conference_member_play_file(member, msg, 0); } static void conference_loop_fn_volume_listen_up(conference_member_t *member, caller_control_action_t *action) @@ -1767,8 +1827,17 @@ static void conference_loop_fn_volume_listen_up(conference_member_t *member, cal } unlock_member(member); - switch_snprintf(msg, sizeof(msg), "Gain level %d", member->volume_in_level); - conference_member_say(member, msg, 0); + //switch_snprintf(msg, sizeof(msg), "Gain level %d", member->volume_in_level); + //conference_member_say(member, msg, 0); + + if (member->volume_in_level < 0) { + switch_snprintf(msg, sizeof(msg), "currency/negative.wav", member->volume_in_level); + conference_member_play_file(member, msg, 0); + } + + switch_snprintf(msg, sizeof(msg), "digits/%d.wav", abs(member->volume_in_level)); + conference_member_play_file(member, msg, 0); + } static void conference_loop_fn_volume_listen_zero(conference_member_t *member, caller_control_action_t *action) @@ -1791,8 +1860,17 @@ static void conference_loop_fn_volume_listen_zero(conference_member_t *member, c } unlock_member(member); - switch_snprintf(msg, sizeof(msg), "Gain level %d", member->volume_in_level); - conference_member_say(member, msg, 0); + //switch_snprintf(msg, sizeof(msg), "Gain level %d", member->volume_in_level); + //conference_member_say(member, msg, 0); + + if (member->volume_in_level < 0) { + switch_snprintf(msg, sizeof(msg), "currency/negative.wav", member->volume_in_level); + conference_member_play_file(member, msg, 0); + } + + switch_snprintf(msg, sizeof(msg), "digits/%d.wav", abs(member->volume_in_level)); + conference_member_play_file(member, msg, 0); + } static void conference_loop_fn_volume_listen_dn(conference_member_t *member, caller_control_action_t *action) @@ -1816,8 +1894,16 @@ static void conference_loop_fn_volume_listen_dn(conference_member_t *member, cal } unlock_member(member); - switch_snprintf(msg, sizeof(msg), "Gain level %d", member->volume_in_level); - conference_member_say(member, msg, 0); + //switch_snprintf(msg, sizeof(msg), "Gain level %d", member->volume_in_level); + //conference_member_say(member, msg, 0); + + if (member->volume_in_level < 0) { + switch_snprintf(msg, sizeof(msg), "currency/negative.wav", member->volume_in_level); + conference_member_play_file(member, msg, 0); + } + + switch_snprintf(msg, sizeof(msg), "digits/%d.wav", abs(member->volume_in_level)); + conference_member_play_file(member, msg, 0); } static void conference_loop_fn_event(conference_member_t *member, caller_control_action_t *action) @@ -1942,16 +2028,79 @@ static void conference_loop_fn_hangup(conference_member_t *member, caller_contro switch_clear_flag_locked(member, MFLAG_RUNNING); } + +static int noise_gate_check(conference_member_t *member) +{ + int r = 0; + + + if (member->conference->agc_level && member->agc_volume_in_level != 0) { + int target_score = 0; + + target_score = (member->energy_level + (25 * member->agc_volume_in_level)); + + if (target_score < 0) target_score = 0; + + r = member->score > target_score; + + } else { + r = member->score > member->energy_level; + } + + return r; +} + static void clear_avg(conference_member_t *member) { - member->agc_volume_in_level = 0; member->avg_score = 0; member->avg_itt = 0; member->avg_tally = 0; - member->nt_tally = 0; + member->agc_concur = 0; } +static void check_agc_levels(conference_member_t *member) +{ + int x = 0, y = member->agc_volume_in_level; + + if (!member->avg_score) return; + + if (member->avg_score < member->conference->agc_level - 100) { + member->agc_volume_in_level++; + switch_normalize_volume_granular(member->agc_volume_in_level); + x = 1; + } else if (member->avg_score > member->conference->agc_level + 100) { + member->agc_volume_in_level--; + switch_normalize_volume_granular(member->agc_volume_in_level); + x = -1; + } + + if (x) { + switch_event_t *event; + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG7, + "AGC %s:%d diff:%d level:%d cur:%d avg:%d vol:%d %s\n", + member->conference->name, + member->id, member->conference->agc_level - member->avg_score, member->conference->agc_level, + member->score, member->avg_score, member->agc_volume_in_level, x > 0 ? "+++" : "---"); + + clear_avg(member); + + + if (test_eflag(member->conference, EFLAG_AUTO_GAIN_LEVEL) && + switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) { + conference_add_event_member_data(member, event); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action", "auto-gain-level"); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Old-Level", "%d", y); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "New-Level", "%d", member->agc_volume_in_level); + switch_event_fire(&event); + } + + } +} + + + /* marshall frames from the call leg to the conference thread for muxing to other call legs */ static void *SWITCH_THREAD_FUNC conference_loop_input(switch_thread_t *thread, void *obj) @@ -1961,8 +2110,7 @@ static void *SWITCH_THREAD_FUNC conference_loop_input(switch_thread_t *thread, v switch_channel_t *channel; switch_status_t status; switch_frame_t *read_frame = NULL; - uint32_t hangover = 40, hangunder = 5, hangover_hits = 0, hangunder_hits = 0, energy_level = 0, diff_level = 400; - switch_codec_implementation_t read_impl = { 0 }; + uint32_t hangover = 40, hangunder = 5, hangover_hits = 0, hangunder_hits = 0, diff_level = 400; switch_core_session_t *session = member->session; int check_floor_change; @@ -1972,7 +2120,7 @@ static void *SWITCH_THREAD_FUNC conference_loop_input(switch_thread_t *thread, v channel = switch_core_session_get_channel(session); - switch_core_session_get_read_impl(session, &read_impl); + switch_core_session_get_read_impl(session, &member->read_impl); /* As long as we have a valid read, feed that data into an input buffer where the conference thread will take it and mux it with any audio from other channels. */ @@ -1997,6 +2145,10 @@ static void *SWITCH_THREAD_FUNC conference_loop_input(switch_thread_t *thread, v } if (switch_test_flag(read_frame, SFF_CNG)) { + if (member->conference->agc_level) { + member->nt_tally++; + } + if (hangunder_hits) { hangunder_hits--; } @@ -2004,6 +2156,7 @@ static void *SWITCH_THREAD_FUNC conference_loop_input(switch_thread_t *thread, v if (++hangover_hits >= hangover) { hangover_hits = hangunder_hits = 0; switch_clear_flag_locked(member, MFLAG_TALKING); + check_agc_levels(member); clear_avg(member); if (test_eflag(member->conference, EFLAG_STOP_TALKING) && @@ -2017,46 +2170,45 @@ static void *SWITCH_THREAD_FUNC conference_loop_input(switch_thread_t *thread, v goto do_continue; } - + + if (member->nt_tally > (member->read_impl.actual_samples_per_second / member->read_impl.samples_per_packet) * 3) { + member->agc_volume_in_level = 0; + clear_avg(member); + } + /* Check for input volume adjustments */ if (!member->conference->agc_level) { + member->conference->agc_level = 0; clear_avg(member); } - energy_level = member->energy_level; /* if the member can speak, compute the audio energy level and */ /* generate events when the level crosses the threshold */ if ((switch_test_flag(member, MFLAG_CAN_SPEAK) || switch_test_flag(member, MFLAG_MUTE_DETECT))) { uint32_t energy = 0, i = 0, samples = 0, j = 0; int16_t *data; - int divisor = 0; - int agc_period = (read_impl.actual_samples_per_second / read_impl.samples_per_packet) / 2; - int combined_vol = 0; + int agc_period = (member->read_impl.actual_samples_per_second / member->read_impl.samples_per_packet) / 4; + data = read_frame->data; - - if (!(divisor = read_impl.actual_samples_per_second / 8000)) { - divisor = 1; - } - member->score = 0; - combined_vol = member->agc_volume_in_level; - if (member->conference->agc_level) { - combined_vol += member->agc_volume_in_level; + if (member->volume_in_level) { + switch_change_sln_volume(read_frame->data, read_frame->datalen / 2, member->volume_in_level); } - if (combined_vol) { - switch_change_sln_volume(read_frame->data, read_frame->datalen / 2, combined_vol); + if (member->agc_volume_in_level) { + switch_change_sln_volume_granular(read_frame->data, read_frame->datalen / 2, member->agc_volume_in_level); } if ((samples = read_frame->datalen / sizeof(*data))) { for (i = 0; i < samples; i++) { energy += abs(data[j]); - j += read_impl.number_of_channels; + j += member->read_impl.number_of_channels; } - member->score = energy / (samples / divisor); + + member->score = energy / samples; } if (member->vol_period) { @@ -2065,39 +2217,37 @@ static void *SWITCH_THREAD_FUNC conference_loop_input(switch_thread_t *thread, v if (member->conference->agc_level && member->score && switch_test_flag(member, MFLAG_CAN_SPEAK) && - member->score > member->conference->agc_energy_level + noise_gate_check(member) ) { - - member->avg_tally += member->score; - member->avg_itt++; - if (!member->avg_itt) member->avg_itt++; - member->avg_score = member->avg_tally / member->avg_itt; + int last_shift = abs(member->last_score - member->score); + if (member->score && member->last_score && last_shift > 900) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG7, + "AGC %s:%d drop anomalous shift of %d\n", + member->conference->name, + member->id, last_shift); + + } else { + member->avg_tally += member->score; + member->avg_itt++; + if (!member->avg_itt) member->avg_itt++; + member->avg_score = member->avg_tally / member->avg_itt; + } switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG7, - "conf %s AGC %d %d %d %d %d %d\n", + "AGC %s:%d diff:%d level:%d cur:%d avg:%d vol:%d\n", member->conference->name, member->id, member->conference->agc_level - member->avg_score, member->conference->agc_level, member->score, member->avg_score, member->agc_volume_in_level); - - - if (++member->nt_tally >= agc_period) { + if (++member->agc_concur >= agc_period) { if (!member->vol_period) { - if (member->avg_score < member->conference->agc_level) { - member->agc_volume_in_level++; - switch_normalize_volume(member->agc_volume_in_level); - member->vol_period = (read_impl.actual_samples_per_second / read_impl.samples_per_packet) * 2; - } - - if (member->avg_score > member->conference->agc_level) { - member->agc_volume_in_level--; - switch_normalize_volume(member->agc_volume_in_level); - member->vol_period = (read_impl.actual_samples_per_second / read_impl.samples_per_packet) * 2; - } + check_agc_levels(member); } - member->nt_tally = 0; + member->agc_concur = 0; } + } else { + member->nt_tally++; } member->score_iir = (int) (((1.0 - SCORE_DECAY) * (float) member->score) + (SCORE_DECAY * (float) member->score_iir)); @@ -2106,12 +2256,16 @@ static void *SWITCH_THREAD_FUNC conference_loop_input(switch_thread_t *thread, v member->score_iir = SCORE_MAX_IIR; } - if (member->score > energy_level) { - uint32_t diff = member->score - energy_level; + if (noise_gate_check(member)) { + uint32_t diff = member->score - member->energy_level; if (hangover_hits) { hangover_hits--; } + if (member->conference->agc_level) { + member->nt_tally = 0; + } + if (diff >= diff_level || ++hangunder_hits >= hangunder) { check_floor_change = 1; @@ -2147,13 +2301,19 @@ static void *SWITCH_THREAD_FUNC conference_loop_input(switch_thread_t *thread, v if (hangunder_hits) { hangunder_hits--; } + + if (member->conference->agc_level) { + member->nt_tally++; + } + if (switch_test_flag(member, MFLAG_TALKING) && switch_test_flag(member, MFLAG_CAN_SPEAK)) { switch_event_t *event; if (++hangover_hits >= hangover) { hangover_hits = hangunder_hits = 0; switch_clear_flag_locked(member, MFLAG_TALKING); + check_agc_levels(member); clear_avg(member); - + if (test_eflag(member->conference, EFLAG_STOP_TALKING) && switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) { conference_add_event_member_data(member, event); @@ -2163,10 +2323,13 @@ static void *SWITCH_THREAD_FUNC conference_loop_input(switch_thread_t *thread, v } } } + + + member->last_score = member->score; } /* skip frames that are not actual media or when we are muted or silent */ - if ((switch_test_flag(member, MFLAG_TALKING) || energy_level == 0) && switch_test_flag(member, MFLAG_CAN_SPEAK) && + if ((switch_test_flag(member, MFLAG_TALKING) || member->energy_level == 0) && switch_test_flag(member, MFLAG_CAN_SPEAK) && !switch_test_flag(member->conference, CFLAG_WAIT_MOD)) { switch_audio_resampler_t *read_resampler = member->read_resampler; void *data; @@ -2689,6 +2852,7 @@ static void *SWITCH_THREAD_FUNC conference_record_thread_run(switch_thread_t *th switch_mutex_init(&member->audio_in_mutex, SWITCH_MUTEX_NESTED, rec->pool); switch_mutex_init(&member->audio_out_mutex, SWITCH_MUTEX_NESTED, rec->pool); switch_mutex_init(&member->read_mutex, SWITCH_MUTEX_NESTED, rec->pool); + switch_thread_rwlock_create(&member->rwlock, rec->pool); /* Setup an audio buffer for the incoming audio */ if (switch_buffer_create_dynamic(&member->audio_buffer, CONF_DBLOCK_SIZE, CONF_DBUFFER_SIZE, 0) != SWITCH_STATUS_SUCCESS) { @@ -3295,6 +3459,30 @@ static void conference_member_itterator(conference_obj_t *conference, switch_str switch_mutex_unlock(conference->member_mutex); } + +static switch_status_t list_conferences(const char *line, const char *cursor, switch_console_callback_match_t **matches) +{ + switch_console_callback_match_t *my_matches = NULL; + switch_status_t status = SWITCH_STATUS_FALSE; + switch_hash_index_t *hi; + void *val; + const void *vvar; + + switch_mutex_lock(globals.hash_mutex); + for (hi = switch_hash_first(NULL, globals.conference_hash); hi; hi = switch_hash_next(hi)) { + switch_hash_this(hi, &vvar, NULL, &val); + switch_console_push_match(&my_matches, (const char *) vvar); + } + switch_mutex_unlock(globals.hash_mutex); + + if (my_matches) { + *matches = my_matches; + status = SWITCH_STATUS_SUCCESS; + } + + return status; +} + static void conference_list_pretty(conference_obj_t *conference, switch_stream_handle_t *stream) { conference_member_t *member = NULL; @@ -3374,8 +3562,11 @@ static void conference_list(conference_obj_t *conference, switch_stream_handle_t count++; } - stream->write_function(stream, "%s%d%s%d%s%d\n", delim, member->agc_volume_in_level ? - member->agc_volume_in_level : member->volume_in_level, delim, member->volume_out_level, delim, member->energy_level); + stream->write_function(stream, "%s%d%s%d%s%d%s%d\n", delim, + member->volume_in_level, + delim, + member->agc_volume_in_level, + delim, member->volume_out_level, delim, member->energy_level); } switch_mutex_unlock(conference->member_mutex); @@ -3389,6 +3580,9 @@ static switch_status_t conf_api_sub_mute(conference_member_t *member, switch_str return SWITCH_STATUS_GENERR; switch_clear_flag_locked(member, MFLAG_CAN_SPEAK); + switch_clear_flag_locked(member, MFLAG_TALKING); + + if (!zstr(member->conference->muted_sound)) { conference_member_play_file(member, member->conference->muted_sound, 0); } else { @@ -3412,7 +3606,7 @@ static switch_status_t conf_api_sub_mute(conference_member_t *member, switch_str static switch_status_t conf_api_sub_agc(conference_obj_t *conference, switch_stream_handle_t *stream, int argc, char **argv) { - int level, energy_level; + int level; int on = 0; if (argc == 2) { @@ -3430,13 +3624,7 @@ static switch_status_t conf_api_sub_agc(conference_obj_t *conference, switch_str if (argc > 3) { level = atoi(argv[3]); } else { - level = 650; - } - - if (argc > 4) { - energy_level = atoi(argv[4]); - } else { - energy_level = 100; + level = DEFAULT_AGC_LEVEL; } if (level > conference->energy_level) { @@ -3444,10 +3632,9 @@ static switch_status_t conf_api_sub_agc(conference_obj_t *conference, switch_str conference->avg_itt = 0; conference->avg_tally = 0; conference->agc_level = level; - conference->agc_energy_level = energy_level; if (stream) { - stream->write_function(stream, "OK AGC ENABLED %d %d\n", conference->agc_level, conference->agc_energy_level); + stream->write_function(stream, "OK AGC ENABLED %d\n", conference->agc_level); } } else { @@ -3821,7 +4008,7 @@ static void conference_xlist(conference_obj_t *conference, switch_xml_t x_confer if (conference->agc_level) { char tmp[30] = ""; - switch_snprintf(tmp, sizeof(tmp), "%d:%d", conference->agc_level, conference->agc_energy_level); + switch_snprintf(tmp, sizeof(tmp), "%d", conference->agc_level); switch_xml_set_attr_d_buf(x_conference, "agc", tmp); } @@ -3909,9 +4096,8 @@ static void conference_xlist(conference_obj_t *conference, switch_xml_t x_confer switch_snprintf(tmp, sizeof(tmp), "%d", member->agc_volume_in_level ? member->agc_volume_in_level : member->volume_in_level); x_tag = add_x_tag(x_member, "input-volume", tmp, toff++); - if (member->agc_volume_in_level) { - switch_xml_set_attr_d(x_tag, "auto", "true"); - } + switch_snprintf(tmp, sizeof(tmp), "%d", member->agc_volume_in_level); + x_tag = add_x_tag(x_member, "auto-adjusted-input-volume", tmp, toff++); } @@ -4007,6 +4193,7 @@ static switch_status_t conf_api_sub_play(conference_obj_t *conference, switch_st } else { stream->write_function(stream, "(play) File: %s not found.\n", argv[2] ? argv[2] : "(unspecified)"); } + switch_thread_rwlock_unlock(member->rwlock); ret_status = SWITCH_STATUS_SUCCESS; } else { stream->write_function(stream, "Member: %u not found.\n", id); @@ -4047,7 +4234,7 @@ static switch_status_t conf_api_sub_saymember(conference_obj_t *conference, swit char *start_text = NULL; char *workspace = NULL; uint32_t id = 0; - conference_member_t *member; + conference_member_t *member = NULL; switch_event_t *event; if (zstr(text)) { @@ -4099,6 +4286,11 @@ static switch_status_t conf_api_sub_saymember(conference_obj_t *conference, swit ret_status = SWITCH_STATUS_SUCCESS; done: + + if (member) { + switch_thread_rwlock_unlock(member->rwlock); + } + switch_safe_free(workspace); switch_safe_free(expanded); return ret_status; @@ -4129,6 +4321,7 @@ static switch_status_t conf_api_sub_stop(conference_obj_t *conference, switch_st if ((member = conference_member_get(conference, id))) { uint32_t stopped = conference_member_stop_file(member, async ? FILE_STOP_ASYNC : current ? FILE_STOP_CURRENT : FILE_STOP_ALL); stream->write_function(stream, "Stopped %u files.\n", stopped); + switch_thread_rwlock_unlock(member->rwlock); } else { stream->write_function(stream, "Member: %u not found.\n", id); } @@ -4168,6 +4361,7 @@ static switch_status_t conf_api_sub_relate(conference_obj_t *conference, switch_ if ((member = conference_member_get(conference, id))) { member_del_relationship(member, oid); stream->write_function(stream, "relationship %u->%u cleared.\n", id, oid); + switch_thread_rwlock_unlock(member->rwlock); } else { stream->write_function(stream, "relationship %u->%u not found.\n", id, oid); } @@ -4179,9 +4373,13 @@ static switch_status_t conf_api_sub_relate(conference_obj_t *conference, switch_ uint32_t id = atoi(argv[2]); uint32_t oid = atoi(argv[3]); - if ((member = conference_member_get(conference, id)) - && (other_member = conference_member_get(conference, oid))) { + if ((member = conference_member_get(conference, id))) { + other_member = conference_member_get(conference, oid); + } + + if (member && other_member) { conference_relationship_t *rel = NULL; + if ((rel = member_get_relationship(member, other_member))) { rel->flags = 0; } else { @@ -4192,6 +4390,7 @@ static switch_status_t conf_api_sub_relate(conference_obj_t *conference, switch_ switch_set_flag(rel, RFLAG_CAN_SPEAK | RFLAG_CAN_HEAR); if (nospeak) { switch_clear_flag(rel, RFLAG_CAN_SPEAK); + switch_clear_flag_locked(member, MFLAG_TALKING); } if (nohear) { switch_clear_flag(rel, RFLAG_CAN_HEAR); @@ -4203,6 +4402,14 @@ static switch_status_t conf_api_sub_relate(conference_obj_t *conference, switch_ } else { stream->write_function(stream, "relationship %u->%u not found.\n", id, oid); } + + if (member) { + switch_thread_rwlock_unlock(member->rwlock); + } + + if (other_member) { + switch_thread_rwlock_unlock(other_member->rwlock); + } } return SWITCH_STATUS_SUCCESS; @@ -4357,6 +4564,7 @@ static switch_status_t conf_api_sub_transfer(conference_obj_t *conference, switc /* Setup a memory pool to use. */ if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Pool Failure\n"); + switch_thread_rwlock_unlock(member->rwlock); goto done; } @@ -4369,6 +4577,7 @@ static switch_status_t conf_api_sub_transfer(conference_obj_t *conference, switc /* Open the config from the xml registry */ if (!(cxml = switch_xml_open_cfg(global_cf_name, &cfg, params))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", global_cf_name); + switch_thread_rwlock_unlock(member->rwlock); goto done; } @@ -4390,6 +4599,7 @@ static switch_status_t conf_api_sub_transfer(conference_obj_t *conference, switc if (pool != NULL) { switch_core_destroy_memory_pool(&pool); } + switch_thread_rwlock_unlock(member->rwlock); goto done; } @@ -4450,6 +4660,10 @@ static switch_status_t conf_api_sub_transfer(conference_obj_t *conference, switc switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action", "transfer"); switch_event_fire(&event); } + + if (member) { + switch_thread_rwlock_unlock(member->rwlock); + } } if (new_conference) { @@ -4569,41 +4783,32 @@ typedef enum { /* API Interface Function sub-commands */ /* Entries in this list should be kept in sync with the enum above */ static api_command_t conf_api_sub_commands[] = { - {"list", (void_fn_t) & conf_api_sub_list, CONF_API_SUB_ARGS_SPLIT, " list [delim ]"}, - {"xml_list", (void_fn_t) & conf_api_sub_xml_list, CONF_API_SUB_ARGS_SPLIT, " xml_list"}, - {"energy", (void_fn_t) & conf_api_sub_energy, CONF_API_SUB_MEMBER_TARGET, - " energy []"}, - {"volume_in", (void_fn_t) & conf_api_sub_volume_in, CONF_API_SUB_MEMBER_TARGET, - " volume_in []"}, - {"volume_out", (void_fn_t) & conf_api_sub_volume_out, CONF_API_SUB_MEMBER_TARGET, - " volume_out []"}, - {"play", (void_fn_t) & conf_api_sub_play, CONF_API_SUB_ARGS_SPLIT, " play [async|]"}, - {"say", (void_fn_t) & conf_api_sub_say, CONF_API_SUB_ARGS_AS_ONE, " say "}, - {"saymember", (void_fn_t) & conf_api_sub_saymember, CONF_API_SUB_ARGS_AS_ONE, - " saymember "}, - {"stop", (void_fn_t) & conf_api_sub_stop, CONF_API_SUB_ARGS_SPLIT, - " stop <[current|all|async|last]> []"}, - {"dtmf", (void_fn_t) & conf_api_sub_dtmf, CONF_API_SUB_MEMBER_TARGET, - " dtmf <[member_id|all|last]> "}, - {"kick", (void_fn_t) & conf_api_sub_kick, CONF_API_SUB_MEMBER_TARGET, " kick <[member_id|all|last]>"}, - {"mute", (void_fn_t) & conf_api_sub_mute, CONF_API_SUB_MEMBER_TARGET, " mute <[member_id|all]|last>"}, - {"unmute", (void_fn_t) & conf_api_sub_unmute, CONF_API_SUB_MEMBER_TARGET, " unmute <[member_id|all]|last>"}, - {"deaf", (void_fn_t) & conf_api_sub_deaf, CONF_API_SUB_MEMBER_TARGET, " deaf <[member_id|all]|last>"}, - {"undeaf", (void_fn_t) & conf_api_sub_undeaf, CONF_API_SUB_MEMBER_TARGET, " undeaf <[member_id|all]|last>"}, - {"relate", (void_fn_t) & conf_api_sub_relate, CONF_API_SUB_ARGS_SPLIT, " relate [nospeak|nohear|clear]"}, - {"lock", (void_fn_t) & conf_api_sub_lock, CONF_API_SUB_ARGS_SPLIT, " lock"}, - {"unlock", (void_fn_t) & conf_api_sub_unlock, CONF_API_SUB_ARGS_SPLIT, " unlock"}, - {"agc", (void_fn_t) & conf_api_sub_agc, CONF_API_SUB_ARGS_SPLIT, " agc"}, - {"dial", (void_fn_t) & conf_api_sub_dial, CONF_API_SUB_ARGS_SPLIT, - " dial / "}, - {"bgdial", (void_fn_t) & conf_api_sub_bgdial, CONF_API_SUB_ARGS_SPLIT, - " bgdial / "}, - {"transfer", (void_fn_t) & conf_api_sub_transfer, CONF_API_SUB_ARGS_SPLIT, - " transfer [...]"}, - {"record", (void_fn_t) & conf_api_sub_record, CONF_API_SUB_ARGS_SPLIT, " record "}, - {"norecord", (void_fn_t) & conf_api_sub_norecord, CONF_API_SUB_ARGS_SPLIT, " norecord <[filename|all]>"}, - {"pin", (void_fn_t) & conf_api_sub_pin, CONF_API_SUB_ARGS_SPLIT, " pin "}, - {"nopin", (void_fn_t) & conf_api_sub_pin, CONF_API_SUB_ARGS_SPLIT, " nopin"}, + {"list", (void_fn_t) & conf_api_sub_list, CONF_API_SUB_ARGS_SPLIT, "list", "[delim ]"}, + {"xml_list", (void_fn_t) & conf_api_sub_xml_list, CONF_API_SUB_ARGS_SPLIT, "xml_list", ""}, + {"energy", (void_fn_t) & conf_api_sub_energy, CONF_API_SUB_MEMBER_TARGET, "energy", " []"}, + {"volume_in", (void_fn_t) & conf_api_sub_volume_in, CONF_API_SUB_MEMBER_TARGET, "volume_in", " []"}, + {"volume_out", (void_fn_t) & conf_api_sub_volume_out, CONF_API_SUB_MEMBER_TARGET, "volume_out", " []"}, + {"play", (void_fn_t) & conf_api_sub_play, CONF_API_SUB_ARGS_SPLIT, "play", " [async|]"}, + {"say", (void_fn_t) & conf_api_sub_say, CONF_API_SUB_ARGS_AS_ONE, "say", ""}, + {"saymember", (void_fn_t) & conf_api_sub_saymember, CONF_API_SUB_ARGS_AS_ONE, "saymember", " "}, + {"stop", (void_fn_t) & conf_api_sub_stop, CONF_API_SUB_ARGS_SPLIT, "stop", "<[current|all|async|last]> []"}, + {"dtmf", (void_fn_t) & conf_api_sub_dtmf, CONF_API_SUB_MEMBER_TARGET, "dtmf", "<[member_id|all|last]> "}, + {"kick", (void_fn_t) & conf_api_sub_kick, CONF_API_SUB_MEMBER_TARGET, "kick", "<[member_id|all|last]>"}, + {"mute", (void_fn_t) & conf_api_sub_mute, CONF_API_SUB_MEMBER_TARGET, "mute", "<[member_id|all]|last>"}, + {"unmute", (void_fn_t) & conf_api_sub_unmute, CONF_API_SUB_MEMBER_TARGET, "unmute", "<[member_id|all]|last>"}, + {"deaf", (void_fn_t) & conf_api_sub_deaf, CONF_API_SUB_MEMBER_TARGET, "deaf", "<[member_id|all]|last>"}, + {"undeaf", (void_fn_t) & conf_api_sub_undeaf, CONF_API_SUB_MEMBER_TARGET, "undeaf", "<[member_id|all]|last>"}, + {"relate", (void_fn_t) & conf_api_sub_relate, CONF_API_SUB_ARGS_SPLIT, "relate", " [nospeak|nohear|clear]"}, + {"lock", (void_fn_t) & conf_api_sub_lock, CONF_API_SUB_ARGS_SPLIT, "lock", ""}, + {"unlock", (void_fn_t) & conf_api_sub_unlock, CONF_API_SUB_ARGS_SPLIT, "unlock", ""}, + {"agc", (void_fn_t) & conf_api_sub_agc, CONF_API_SUB_ARGS_SPLIT, "agc", ""}, + {"dial", (void_fn_t) & conf_api_sub_dial, CONF_API_SUB_ARGS_SPLIT, "dial", "/ "}, + {"bgdial", (void_fn_t) & conf_api_sub_bgdial, CONF_API_SUB_ARGS_SPLIT, "bgdial", "/ "}, + {"transfer", (void_fn_t) & conf_api_sub_transfer, CONF_API_SUB_ARGS_SPLIT, "transfer", " [...]"}, + {"record", (void_fn_t) & conf_api_sub_record, CONF_API_SUB_ARGS_SPLIT, "record", ""}, + {"norecord", (void_fn_t) & conf_api_sub_norecord, CONF_API_SUB_ARGS_SPLIT, "norecord", "<[filename|all]>"}, + {"pin", (void_fn_t) & conf_api_sub_pin, CONF_API_SUB_ARGS_SPLIT, "pin", ""}, + {"nopin", (void_fn_t) & conf_api_sub_pin, CONF_API_SUB_ARGS_SPLIT, "nopin", ""}, }; #define CONFFUNCAPISIZE (sizeof(conf_api_sub_commands)/sizeof(conf_api_sub_commands[0])) @@ -4628,7 +4833,7 @@ switch_status_t conf_api_dispatch(conference_obj_t *conference, switch_stream_ha if (pfn(conference, stream, argc, argv) != SWITCH_STATUS_SUCCESS) { /* command returned error, so show syntax usage */ - stream->write_function(stream, conf_api_sub_commands[i].psyntax); + stream->write_function(stream, "%s %s", conf_api_sub_commands[i].pcommand, conf_api_sub_commands[i].psyntax); } } break; @@ -4677,11 +4882,12 @@ switch_status_t conf_api_dispatch(conference_obj_t *conference, switch_stream_ha if (member != NULL) { pfn(member, stream, argv[argn + 2]); + switch_thread_rwlock_unlock(member->rwlock); } else { stream->write_function(stream, "Non-Existant ID %u\n", id); } } else { - stream->write_function(stream, conf_api_sub_commands[i].psyntax); + stream->write_function(stream, "%s %s", conf_api_sub_commands[i].pcommand, conf_api_sub_commands[i].psyntax); } } break; @@ -4704,7 +4910,7 @@ switch_status_t conf_api_dispatch(conference_obj_t *conference, switch_stream_ha /* call the command handler */ if (pfn(conference, stream, modified_cmdline) != SWITCH_STATUS_SUCCESS) { /* command returned error, so show syntax usage */ - stream->write_function(stream, conf_api_sub_commands[i].psyntax); + stream->write_function(stream, "%s %s", conf_api_sub_commands[i].pcommand, conf_api_sub_commands[i].psyntax); } } break; @@ -4779,12 +4985,14 @@ SWITCH_STANDARD_API(conf_api_main) } else if (argv[1] && strcasecmp(argv[1], "dial") == 0) { if (conf_api_sub_dial(NULL, stream, argc, argv) != SWITCH_STATUS_SUCCESS) { /* command returned error, so show syntax usage */ - stream->write_function(stream, conf_api_sub_commands[CONF_API_COMMAND_DIAL].psyntax); + stream->write_function(stream, "%s %s", conf_api_sub_commands[CONF_API_COMMAND_DIAL].pcommand, + conf_api_sub_commands[CONF_API_COMMAND_DIAL].psyntax); } } else if (argv[1] && strcasecmp(argv[1], "bgdial") == 0) { if (conf_api_sub_bgdial(NULL, stream, argc, argv) != SWITCH_STATUS_SUCCESS) { /* command returned error, so show syntax usage */ - stream->write_function(stream, conf_api_sub_commands[CONF_API_COMMAND_BGDIAL].psyntax); + stream->write_function(stream, "%s %s", conf_api_sub_commands[CONF_API_COMMAND_BGDIAL].pcommand, + conf_api_sub_commands[CONF_API_COMMAND_BGDIAL].psyntax); } } else { stream->write_function(stream, "Conference %s not found\n", argv[0]); @@ -4792,7 +5000,11 @@ SWITCH_STANDARD_API(conf_api_main) } } else { - stream->write_function(stream, "No parameters specified.\nTry 'help conference'\n"); + int i; + + for (i = 0; i < CONFFUNCAPISIZE; i++) { + stream->write_function(stream, " %s %s\n", conf_api_sub_commands[i].pcommand, conf_api_sub_commands[i].psyntax); + } } done: @@ -5127,6 +5339,7 @@ static void set_mflags(const char *flags, member_flag_t *f) for (i = 0; i < argc && argv[i]; i++) { if (!strcasecmp(argv[i], "mute")) { *f &= ~MFLAG_CAN_SPEAK; + *f &= ~MFLAG_TALKING; } else if (!strcasecmp(argv[i], "deaf")) { *f &= ~MFLAG_CAN_HEAR; } else if (!strcasecmp(argv[i], "waste")) { @@ -5785,6 +5998,7 @@ SWITCH_STANDARD_APP(conference_function) switch_mutex_init(&member.read_mutex, SWITCH_MUTEX_NESTED, member.pool); switch_mutex_init(&member.audio_in_mutex, SWITCH_MUTEX_NESTED, member.pool); switch_mutex_init(&member.audio_out_mutex, SWITCH_MUTEX_NESTED, member.pool); + switch_thread_rwlock_create(&member.rwlock, member.pool); /* Install our Signed Linear codec so we get the audio in that format */ switch_core_session_set_read_codec(member.session, &member.read_codec); @@ -6208,6 +6422,7 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_c comfort_noise_level = 1400; } } else if (!strcasecmp(var, "sound-prefix") && !zstr(val)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "override sound-prefix with: %s\n", val); sound_prefix = val; } else if (!strcasecmp(var, "max-members") && !zstr(val)) { errno = 0; /* sanity first */ @@ -6312,8 +6527,15 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_c set_cflags(conference_flags, &conference->flags); } - if (sound_prefix) { + if (!zstr(sound_prefix)) { conference->sound_prefix = switch_core_strdup(conference->pool, sound_prefix); + } else { + const char *val; + if ((val = switch_channel_get_variable(channel, "sound_prefix")) && !zstr(val)) { + /* if no sound_prefix was set, use the channel sound_prefix */ + conference->sound_prefix = switch_core_strdup(conference->pool, val); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "using channel sound prefix: %s\n", conference->sound_prefix); + } } if (!zstr(enter_sound)) { @@ -6389,30 +6611,16 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_c if (!zstr(auto_gain_level)) { int level = 0; - int energy_level = 100; if (switch_true(auto_gain_level)) { - level = 650; + level = DEFAULT_AGC_LEVEL; } else { - char *p; - int tmp = 0; - level = atoi(auto_gain_level); - if ((p = strchr(auto_gain_level, ':'))) { - p++; - if (p) tmp = atoi(p); - if (tmp > 0) { - energy_level = tmp; - } - } } if (level > 0 && level > conference->energy_level) { conference->agc_level = level; } - - conference->agc_energy_level = energy_level; - } if (!zstr(maxmember_sound)) { @@ -6717,16 +6925,25 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_conference_load) switch_api_interface_t *api_interface; switch_application_interface_t *app_interface; switch_status_t status = SWITCH_STATUS_SUCCESS; + char cmd_str[256]; memset(&globals, 0, sizeof(globals)); /* Connect my internal structure to the blank pointer passed to me */ *module_interface = switch_loadable_module_create_module_interface(pool, modname); + switch_console_add_complete_func("::conference::list_conferences", list_conferences); + + /* build api interface help ".syntax" field string */ p = strdup(""); for (i = 0; i < CONFFUNCAPISIZE; i++) { - nl = strlen(conf_api_sub_commands[i].psyntax) + 4; + nl = strlen(conf_api_sub_commands[i].pcommand) + strlen(conf_api_sub_commands[i].psyntax) + 5; + + switch_snprintf(cmd_str, sizeof(cmd_str), "add conference ::conference::list_conferences %s", conf_api_sub_commands[i].pcommand); + + switch_console_set_complete(cmd_str); + if (p != NULL) { ol = strlen(p); } @@ -6734,7 +6951,11 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_conference_load) if (tmp != NULL) { p = tmp; strcat(p, "\t\t"); - strcat(p, conf_api_sub_commands[i].psyntax); + strcat(p, conf_api_sub_commands[i].pcommand); + if (!zstr(conf_api_sub_commands[i].psyntax)) { + strcat(p, " "); + strcat(p, conf_api_sub_commands[i].psyntax); + } if (i < CONFFUNCAPISIZE - 1) { strcat(p, "\n"); } @@ -6773,6 +6994,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_conference_load) SWITCH_ADD_APP(app_interface, global_app_name, global_app_name, NULL, conference_function, NULL, SAF_NONE); SWITCH_ADD_APP(app_interface, "conference_set_auto_outcall", "conference_set_auto_outcall", NULL, conference_auto_function, NULL, SAF_NONE); SWITCH_ADD_CHAT(chat_interface, CONF_CHAT_PROTO, chat_send); + send_presence(SWITCH_EVENT_PRESENCE_IN); @@ -6788,6 +7010,8 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_conference_shutdown) /* signal all threads to shutdown */ globals.running = 0; + switch_console_del_complete_func("::conference::list_conferences"); + /* wait for all threads */ while (globals.threads) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Waiting for %d threads\n", globals.threads); diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c index 9a1258a5b6..346cdaa9f8 100755 --- a/src/mod/applications/mod_dptools/mod_dptools.c +++ b/src/mod/applications/mod_dptools/mod_dptools.c @@ -2893,7 +2893,7 @@ static switch_call_cause_t user_outgoing_channel(switch_core_session_t *session, switch_xml_t x_domain = NULL, xml = NULL, x_user = NULL, x_group = NULL, x_param, x_params; char *user = NULL, *domain = NULL, *dup_domain = NULL; const char *dest = NULL; - static switch_call_cause_t cause = SWITCH_CAUSE_NONE; + switch_call_cause_t cause = SWITCH_CAUSE_NONE; unsigned int timelimit = 60; switch_channel_t *new_channel = NULL; switch_event_t *params = NULL, *var_event_orig = var_event; diff --git a/src/mod/applications/mod_lcr/mod_lcr.c b/src/mod/applications/mod_lcr/mod_lcr.c index 2f2bc7d421..593117942a 100644 --- a/src/mod/applications/mod_lcr/mod_lcr.c +++ b/src/mod/applications/mod_lcr/mod_lcr.c @@ -595,11 +595,12 @@ static int route_add_callback(void *pArg, int argc, char **argv, char **columnNa callback_t *cbt = (callback_t *) pArg; char *key = NULL; int i = 0; + int r = 0; switch_memory_pool_t *pool = cbt->pool; additional = switch_core_alloc(pool, sizeof(lcr_obj_t)); - additional->fields = switch_core_alloc(pool, sizeof(switch_event_t)); + switch_event_create(&additional->fields, SWITCH_EVENT_REQUEST_PARAMS); for (i = 0; i < argc ; i++) { if (CF("lcr_digits")) { @@ -652,9 +653,9 @@ static int route_add_callback(void *pArg, int argc, char **argv, char **columnNa switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Adding %s to head of list\n", additional->carrier_name); if (switch_core_hash_insert(cbt->dedup_hash, key, additional) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error inserting into dedup hash\n"); - return SWITCH_STATUS_GENERR; + r = -1; goto end; } - return SWITCH_STATUS_SUCCESS; + r = 0; goto end; } @@ -676,7 +677,7 @@ static int route_add_callback(void *pArg, int argc, char **argv, char **columnNa additional->prev = current; if (switch_core_hash_insert(cbt->dedup_hash, key, additional) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error inserting into dedup hash\n"); - return SWITCH_STATUS_GENERR; + r = -1; goto end; } break; } @@ -697,7 +698,7 @@ static int route_add_callback(void *pArg, int argc, char **argv, char **columnNa current->prev = additional; if (switch_core_hash_insert(cbt->dedup_hash, key, additional) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error inserting into dedup hash\n"); - return SWITCH_STATUS_GENERR; + r = -1; goto end; } break; } else if (current->next == NULL) { @@ -707,13 +708,19 @@ static int route_add_callback(void *pArg, int argc, char **argv, char **columnNa additional->prev = current; if (switch_core_hash_insert(cbt->dedup_hash, key, additional) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error inserting into dedup hash\n"); - return SWITCH_STATUS_GENERR; + r = -1; goto end; } break; } } } - return SWITCH_STATUS_SUCCESS; + + end: + + switch_event_destroy(&additional->fields); + + return r; + } static int intrastatelata_callback(void *pArg, int argc, char **argv, char **columnNames) diff --git a/src/mod/applications/mod_valet_parking/mod_valet_parking.c b/src/mod/applications/mod_valet_parking/mod_valet_parking.c index 42ece97e28..14412bc318 100644 --- a/src/mod/applications/mod_valet_parking/mod_valet_parking.c +++ b/src/mod/applications/mod_valet_parking/mod_valet_parking.c @@ -114,7 +114,13 @@ SWITCH_STANDARD_APP(valet_parking_function) switch_channel_t *channel = switch_core_session_get_channel(session); switch_event_t *event; char dtmf_buf[128] = ""; - int is_auto = 0; + int is_auto = 0, play_announce = 1; + const char *var; + + + if ((var = switch_channel_get_variable(channel, "valet_announce_slot"))) { + play_announce = switch_true(var); + } if (!zstr(data) && (lbuf = switch_core_session_strdup(session, data)) && (argc = switch_separate_string(lbuf, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) >= 2) { @@ -254,7 +260,9 @@ SWITCH_STANDARD_APP(valet_parking_function) switch_core_session_t *b_session; if ((b_session = switch_core_session_locate(uuid))) { - switch_ivr_phrase_macro(session, "valet_announce_ext", tmp, NULL, NULL); + if (play_announce) { + switch_ivr_phrase_macro(session, "valet_announce_ext", tmp, NULL, NULL); + } switch_ivr_session_transfer(b_session, dest, "inline", NULL); switch_mutex_unlock(lot->mutex); switch_core_session_rwunlock(b_session); @@ -263,7 +271,9 @@ SWITCH_STANDARD_APP(valet_parking_function) } } - switch_ivr_phrase_macro(session, "valet_announce_ext", tmp, NULL, NULL); + if (play_announce) { + switch_ivr_phrase_macro(session, "valet_announce_ext", tmp, NULL, NULL); + } } diff --git a/src/mod/asr_tts/mod_unimrcp/mod_unimrcp.c b/src/mod/asr_tts/mod_unimrcp/mod_unimrcp.c index d5bac5f7f4..8698e4a02c 100644 --- a/src/mod/asr_tts/mod_unimrcp/mod_unimrcp.c +++ b/src/mod/asr_tts/mod_unimrcp/mod_unimrcp.c @@ -3155,15 +3155,19 @@ static switch_status_t recog_asr_disable_all_grammars(switch_asr_handle_t *ah) static switch_status_t recog_asr_close(switch_asr_handle_t *ah, switch_asr_flag_t *flags) { speech_channel_t *schannel = (speech_channel_t *) ah->private_info; - recognizer_data_t *r = (recognizer_data_t *) schannel->data; - speech_channel_stop(schannel); - speech_channel_destroy(schannel); - switch_core_hash_destroy(&r->grammars); - switch_core_hash_destroy(&r->enabled_grammars); - if (r->dtmf_generator) { - mpf_dtmf_generator_destroy(r->dtmf_generator); - } + recognizer_data_t *r = NULL; + /* close if not already closed */ + if (schannel != NULL && !switch_test_flag(ah, SWITCH_ASR_FLAG_CLOSED)) { + r = (recognizer_data_t *) schannel->data; + speech_channel_stop(schannel); + speech_channel_destroy(schannel); + switch_core_hash_destroy(&r->grammars); + switch_core_hash_destroy(&r->enabled_grammars); + if (r->dtmf_generator) { + mpf_dtmf_generator_destroy(r->dtmf_generator); + } + } /* this lets FreeSWITCH's speech_thread know the handle is closed */ switch_set_flag(ah, SWITCH_ASR_FLAG_CLOSED); diff --git a/src/mod/codecs/mod_sangoma_codec/mod_sangoma_codec.c b/src/mod/codecs/mod_sangoma_codec/mod_sangoma_codec.c index 97d9f6de9e..dd97453c7a 100644 --- a/src/mod/codecs/mod_sangoma_codec/mod_sangoma_codec.c +++ b/src/mod/codecs/mod_sangoma_codec/mod_sangoma_codec.c @@ -227,6 +227,23 @@ static int sangoma_create_rtp_port(void *usr_priv, uint32_t host_ip, uint32_t *p return 0; } +static int sangoma_release_rtp_port(void *usr_priv, uint32_t host_ip, uint32_t p_rtp_port, void *rtp_fd) +{ + struct in_addr local_ip_addr = { 0 }; + char local_ip[255]; + switch_port_t rtp_port = p_rtp_port; + + local_ip_addr.s_addr = htonl(host_ip); + + switch_inet_ntop(AF_INET, &local_ip_addr, local_ip, sizeof(local_ip)); + + /* release the port */ + switch_rtp_release_port(local_ip, rtp_port); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Released port %d for IP %s/%d.%d.%d.%d\n", rtp_port, local_ip, + SNGTC_NIPV4(host_ip)); + return 0; +} + static int sangoma_create_rtp(void *usr_priv, sngtc_codec_request_leg_t *codec_req_leg, sngtc_codec_reply_leg_t* codec_reply_leg, void **rtp_fd) { switch_status_t status; @@ -1180,6 +1197,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sangoma_codec_load) g_init_cfg.create_rtp = sangoma_create_rtp; g_init_cfg.create_rtp_port = sangoma_create_rtp_port; g_init_cfg.destroy_rtp = sangoma_destroy_rtp; + g_init_cfg.release_rtp_port = sangoma_release_rtp_port; if (sngtc_detect_init_modules(&g_init_cfg, &detected)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to detect vocallo modules\n"); diff --git a/src/mod/endpoints/mod_dingaling/mod_dingaling.c b/src/mod/endpoints/mod_dingaling/mod_dingaling.c index 9fb1f39e11..7cd9e5618b 100644 --- a/src/mod/endpoints/mod_dingaling/mod_dingaling.c +++ b/src/mod/endpoints/mod_dingaling/mod_dingaling.c @@ -77,6 +77,7 @@ typedef enum { TFLAG_TERM = (1 << 20), TFLAG_TRANSPORT_ACCEPT = (1 << 21), TFLAG_READY = (1 << 22), + TFLAG_NAT_MAP = (1 << 22) } TFLAGS; typedef enum { @@ -158,6 +159,7 @@ struct private_object { ldl_session_t *dlsession; char *remote_ip; switch_port_t local_port; + switch_port_t adv_local_port; switch_port_t remote_port; char local_user[17]; char local_pass[17]; @@ -596,9 +598,9 @@ static void ipchanged_event_handler(switch_event_t *event) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "EVENT_TRAP: IP change detected\n"); - if (cond && !strcmp(cond, "network-address-change")) { - const char *old_ip4 = switch_event_get_header_nil(event, "network-address-previous-v4"); - const char *new_ip4 = switch_event_get_header_nil(event, "network-address-change-v4"); + if (cond && !strcmp(cond, "network-external-address-change")) { + const char *old_ip4 = switch_event_get_header_nil(event, "network-external-address-previous-v4"); + const char *new_ip4 = switch_event_get_header_nil(event, "network-external-address-change-v4"); switch_hash_index_t *hi; void *val; char *tmp; @@ -886,11 +888,22 @@ static int activate_rtp(struct private_object *tech_pvt) if (globals.auto_nat && tech_pvt->profile->local_network && !switch_check_network_list_ip(tech_pvt->remote_ip, tech_pvt->profile->local_network)) { switch_port_t external_port = 0; switch_nat_add_mapping((switch_port_t) tech_pvt->local_port, SWITCH_NAT_UDP, &external_port, SWITCH_FALSE); - tech_pvt->local_port = external_port; + + if (external_port) { + tech_pvt->adv_local_port = external_port; + switch_set_flag(tech_pvt, TFLAG_NAT_MAP); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "NAT mapping returned 0. Run freeswitch with -nonat since it's not working right.\n"); + } } - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "SETUP RTP %s:%d -> %s:%d\n", tech_pvt->profile->ip, - tech_pvt->local_port, tech_pvt->remote_ip, tech_pvt->remote_port); + if (tech_pvt->adv_local_port != tech_pvt->local_port) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "SETUP RTP %s:%d(%d) -> %s:%d\n", tech_pvt->profile->ip, + tech_pvt->local_port, tech_pvt->adv_local_port, tech_pvt->remote_ip, tech_pvt->remote_port); + } else { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "SETUP RTP %s:%d -> %s:%d\n", tech_pvt->profile->ip, + tech_pvt->local_port, tech_pvt->remote_ip, tech_pvt->remote_port); + } flags = SWITCH_RTP_FLAG_DATAWAIT | SWITCH_RTP_FLAG_GOOGLEHACK | SWITCH_RTP_FLAG_AUTOADJ | SWITCH_RTP_FLAG_RAW_WRITE | SWITCH_RTP_FLAG_AUTO_CNG; @@ -964,7 +977,7 @@ static int do_candidates(struct private_object *tech_pvt, int force) } - cand[0].port = tech_pvt->local_port; + cand[0].port = tech_pvt->adv_local_port; cand[0].address = advip; if (!strncasecmp(advip, "stun:", 5)) { @@ -1253,9 +1266,9 @@ static switch_status_t channel_on_destroy(switch_core_session_t *session) tech_pvt->rtp_session = NULL; } - if (globals.auto_nat && tech_pvt->profile->local_network && tech_pvt->remote_ip && tech_pvt->profile->local_network && - !switch_check_network_list_ip(tech_pvt->remote_ip, tech_pvt->profile->local_network)) { - switch_nat_del_mapping((switch_port_t) tech_pvt->local_port, SWITCH_NAT_UDP); + if (switch_test_flag(tech_pvt, TFLAG_NAT_MAP)) { + switch_nat_del_mapping((switch_port_t) tech_pvt->adv_local_port, SWITCH_NAT_UDP); + switch_clear_flag(tech_pvt, TFLAG_NAT_MAP); } if (switch_core_codec_ready(&tech_pvt->read_codec)) { @@ -1751,6 +1764,7 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi terminate_session(new_session, __LINE__, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; } + tech_pvt->adv_local_port = tech_pvt->local_port; tech_pvt->recip = switch_core_session_strdup(*new_session, full_id); if (dnis) { tech_pvt->dnis = switch_core_session_strdup(*new_session, dnis); @@ -2992,6 +3006,7 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi status = LDL_STATUS_FALSE; goto done; } + tech_pvt->adv_local_port = tech_pvt->local_port; switch_set_flag_locked(tech_pvt, TFLAG_ANSWER); tech_pvt->recip = switch_core_session_strdup(session, from); if (!(exten = ldl_session_get_value(dlsession, "dnis"))) { diff --git a/src/mod/endpoints/mod_skinny/mod_skinny.c b/src/mod/endpoints/mod_skinny/mod_skinny.c index 5320ca52d1..b05806b8d9 100644 --- a/src/mod/endpoints/mod_skinny/mod_skinny.c +++ b/src/mod/endpoints/mod_skinny/mod_skinny.c @@ -651,7 +651,7 @@ int channel_on_routing_callback(void *pArg, int argc, char **argv, char **column } else { 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_IN_USE_REMOTELY); - send_select_soft_keys(listener, line_instance, helper->tech_pvt->call_id, 10, 0xffff); + send_select_soft_keys(listener, line_instance, helper->tech_pvt->call_id, SKINNY_KEY_SET_IN_USE_HINT, 0xffff); send_display_prompt_status(listener, 0, SKINNY_DISP_IN_USE_REMOTE, line_instance, helper->tech_pvt->call_id); skinny_session_send_call_info(helper->tech_pvt->session, listener, line_instance); @@ -1243,6 +1243,21 @@ static void walk_listeners(skinny_listener_callback_func_t callback, void *pvt) switch_mutex_unlock(globals.mutex); } +static int flush_listener_callback(void *pArg, int argc, char **argv, char **columnNames) +{ + char *profile_name = argv[0]; + char *value = argv[1]; + char *domain_name = argv[2]; + char *device_name = argv[3]; + char *device_instance = argv[4]; + + char *token = switch_mprintf("skinny/%q/%q/%q:%q", profile_name, value, device_name, device_instance); + switch_core_del_registration(value, domain_name, token); + switch_safe_free(token); + + return 0; +} + static void flush_listener(listener_t *listener) { @@ -1250,6 +1265,18 @@ static void flush_listener(listener_t *listener) skinny_profile_t *profile = listener->profile; char *sql; + if ((sql = switch_mprintf( + "SELECT '%q', value, '%q', '%q', '%d' " + "FROM skinny_lines " + "WHERE device_name='%s' AND device_instance=%d " + "ORDER BY position", + profile->name, profile->domain, listener->device_name, listener->device_instance, + listener->device_name, listener->device_instance + ))) { + skinny_execute_sql_callback(profile, profile->sql_mutex, sql, flush_listener_callback, NULL); + switch_safe_free(sql); + } + if ((sql = switch_mprintf( "DELETE FROM skinny_devices " "WHERE name='%s' and instance=%d", @@ -1488,6 +1515,8 @@ static void *SWITCH_THREAD_FUNC skinny_profile_run(switch_thread_t *thread, void listener_t *listener; switch_memory_pool_t *tmp_pool = NULL, *listener_pool = NULL; uint32_t errs = 0; + switch_sockaddr_t *local_sa = NULL; + switch_sockaddr_t *remote_sa =NULL; if (switch_core_new_memory_pool(&tmp_pool) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "OH OH no pool\n"); @@ -1496,8 +1525,9 @@ static void *SWITCH_THREAD_FUNC skinny_profile_run(switch_thread_t *thread, void new_socket: while(globals.running) { + char *listening_ip = NULL; switch_clear_flag_locked(profile, PFLAG_RESPAWN); - rv = switch_sockaddr_info_get(&sa, profile->ip, SWITCH_INET, profile->port, 0, tmp_pool); + rv = switch_sockaddr_info_get(&sa, profile->ip, SWITCH_UNSPEC, profile->port, 0, tmp_pool); if (rv) goto fail; rv = switch_socket_create(&profile->sock, switch_sockaddr_get_family(sa), SOCK_STREAM, SWITCH_PROTO_TCP, tmp_pool); @@ -1512,6 +1542,10 @@ new_socket: rv = switch_socket_listen(profile->sock, 5); if (rv) goto sock_fail; + switch_sockaddr_ip_get(&listening_ip, sa); + if (!profile->ip || strcmp(listening_ip, profile->ip)) { + profile->ip = switch_core_strdup(profile->pool, listening_ip); + } switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Socket up listening on %s:%u\n", profile->ip, profile->port); break; @@ -1566,9 +1600,14 @@ new_socket: switch_mutex_init(&listener->flag_mutex, SWITCH_MUTEX_NESTED, listener->pool); - switch_socket_addr_get(&listener->sa, SWITCH_TRUE, listener->sock); - switch_get_addr(listener->remote_ip, sizeof(listener->remote_ip), listener->sa); - listener->remote_port = switch_sockaddr_get_port(listener->sa); + switch_socket_addr_get(&remote_sa, SWITCH_TRUE, listener->sock); + switch_get_addr(listener->remote_ip, sizeof(listener->remote_ip), remote_sa); + listener->remote_port = switch_sockaddr_get_port(remote_sa); + + switch_socket_addr_get(&local_sa, SWITCH_FALSE, listener->sock); + switch_get_addr(listener->local_ip, sizeof(listener->local_ip), local_sa); + listener->local_port = switch_sockaddr_get_port(local_sa); + launch_listener_thread(listener); } @@ -1636,7 +1675,7 @@ switch_status_t skinny_profile_set(skinny_profile_t *profile, const char *var, c profile->domain = switch_core_strdup(profile->pool, val); } else if (!strcasecmp(var, "ip")) { if (!profile->ip || strcmp(val, profile->ip)) { - profile->ip = switch_core_strdup(profile->pool, val); + profile->ip = switch_core_strdup(profile->pool, zstr(val) ? NULL : val); switch_set_flag_locked(profile, PFLAG_SHOULD_RESPAWN); } } else if (!strcasecmp(var, "port")) { @@ -1784,6 +1823,9 @@ static switch_status_t load_skinny_config(void) size_t string_len = strlen(val); size_t string_pos, start = 0; int field_no = 0; + if (zstr(val)) { + continue; + } if (soft_key_set_id > 15) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "soft-key-set name '%s' is greater than 15 in soft-key-set-set '%s' in profile %s.\n", diff --git a/src/mod/endpoints/mod_skinny/mod_skinny.h b/src/mod/endpoints/mod_skinny/mod_skinny.h index 20d68faba5..eb7e45ebc0 100644 --- a/src/mod/endpoints/mod_skinny/mod_skinny.h +++ b/src/mod/endpoints/mod_skinny/mod_skinny.h @@ -132,25 +132,25 @@ typedef enum { #define SKINNY_MAX_LINES 42 struct listener { - skinny_profile_t *profile; - char device_name[16]; - uint32_t device_instance; - uint32_t device_type; - + skinny_profile_t *profile; + char device_name[16]; + uint32_t device_instance; + uint32_t device_type; + char firmware_version[16]; char *soft_key_set_set; - switch_socket_t *sock; - switch_memory_pool_t *pool; - switch_thread_rwlock_t *rwlock; - switch_sockaddr_t *sa; - char remote_ip[50]; - switch_mutex_t *flag_mutex; - uint32_t flags; - switch_port_t remote_port; - uint32_t id; - time_t expire_time; - struct listener *next; + switch_socket_t *sock; + switch_memory_pool_t *pool; + switch_thread_rwlock_t *rwlock; + char remote_ip[50]; + switch_port_t remote_port; + char local_ip[50]; + switch_port_t local_port; + switch_mutex_t *flag_mutex; + uint32_t flags; + time_t expire_time; + struct listener *next; }; typedef struct listener listener_t; diff --git a/src/mod/endpoints/mod_skinny/skinny_protocol.c b/src/mod/endpoints/mod_skinny/skinny_protocol.c index 743514d98c..4c09c70176 100644 --- a/src/mod/endpoints/mod_skinny/skinny_protocol.c +++ b/src/mod/endpoints/mod_skinny/skinny_protocol.c @@ -43,10 +43,10 @@ char* skinny_codec2string(enum skinny_codecs skinnycodec) switch (skinnycodec) { case SKINNY_CODEC_ALAW_64K: case SKINNY_CODEC_ALAW_56K: - return "ALAW"; + return "PCMA"; case SKINNY_CODEC_ULAW_64K: case SKINNY_CODEC_ULAW_56K: - return "ULAW"; + return "PCMU"; case SKINNY_CODEC_G722_64K: case SKINNY_CODEC_G722_56K: case SKINNY_CODEC_G722_48K: diff --git a/src/mod/endpoints/mod_skinny/skinny_protocol.h b/src/mod/endpoints/mod_skinny/skinny_protocol.h index 1a26558ffc..8f8911f2a7 100644 --- a/src/mod/endpoints/mod_skinny/skinny_protocol.h +++ b/src/mod/endpoints/mod_skinny/skinny_protocol.h @@ -97,6 +97,12 @@ struct PACKED on_hook_message { uint32_t call_id; }; +/* ForwardStatReqMessage */ +#define FORWARD_STAT_REQ_MESSAGE 0x0009 +struct PACKED forward_stat_req_message { + uint32_t line_instance; +}; + /* SpeedDialStatReqMessage */ #define SPEED_DIAL_STAT_REQ_MESSAGE 0x000A struct PACKED speed_dial_stat_req_message { @@ -125,7 +131,7 @@ struct PACKED line_stat_req_message { #define CAPABILITIES_RES_MESSAGE 0x0010 struct PACKED station_capabilities { uint32_t codec; - uint16_t frames; + uint16_t max_frames_per_packet; char reserved[10]; }; @@ -328,6 +334,19 @@ struct PACKED call_info_message { uint32_t party_pi_restriction_bits; }; +/* ForwardStatMessage */ +#define FORWARD_STAT_MESSAGE 0x0090 +struct PACKED forward_stat_message { + uint32_t active_forward; + uint32_t line_instance; + uint32_t forward_all_active; + char forward_all_number[24]; + uint32_t forward_busy_active; + char forward_busy_number[24]; + uint32_t forward_noanswer_active; + char forward_noanswer_number[24]; +}; + /* SpeedDialStatMessage */ #define SPEED_DIAL_STAT_RES_MESSAGE 0x0091 struct PACKED speed_dial_stat_res_message { @@ -566,76 +585,78 @@ struct PACKED service_url_stat_res_message { union skinny_data { /* no data for KEEP_ALIVE_MESSAGE */ - struct register_message reg; - struct port_message port; - struct keypad_button_message keypad_button; - struct enbloc_call_message enbloc_call; - struct stimulus_message stimulus; - struct off_hook_message off_hook; - struct on_hook_message on_hook; - struct speed_dial_stat_req_message speed_dial_req; - struct line_stat_req_message line_req; - /* no data for CONFIG_STAT_REQ_MESSAGE */ - /* no data for TIME_DATE_REQ_MESSAGE */ - /* no data for BUTTON_TEMPLATE_REQ_MESSAGE */ - /* no data for VERSION_REQ_MESSAGE */ - struct capabilities_res_message cap_res; - struct alarm_message alarm; - struct open_receive_channel_ack_message open_receive_channel_ack; - /* no data for SOFT_KEY_SET_REQ_MESSAGE */ - struct soft_key_event_message soft_key_event; - /* no data for UNREGISTER_MESSAGE */ - /* no data for SOFT_KEY_TEMPLATE_REQ_MESSAGE */ - struct headset_status_message headset_status; - struct register_available_lines_message reg_lines; - /* see field "data" for DEVICE_TO_USER_DATA_MESSAGE */ - /* see field "data" for DEVICE_TO_USER_DATA_RESPONSE_MESSAGE */ - struct service_url_stat_req_message service_url_req; - struct feature_stat_req_message feature_req; - /* see field "extended_data" for DEVICE_TO_USER_DATA_VERSION1_MESSAGE */ - /* see field "extended_data" for DEVICE_TO_USER_DATA_RESPONSE_VERSION1_MESSAGE */ - struct register_ack_message reg_ack; - struct start_tone_message start_tone; - struct stop_tone_message stop_tone; - struct set_ringer_message ringer; - struct set_lamp_message lamp; - struct set_speaker_mode_message speaker_mode; - struct start_media_transmission_message start_media; - struct stop_media_transmission_message stop_media; - struct call_info_message call_info; - struct speed_dial_stat_res_message speed_dial_res; - struct line_stat_res_message line_res; - struct config_stat_res_message config_res; - struct define_time_date_message define_time_date; - struct button_template_message button_template; - struct version_message version; - /* no data for CAPABILITIES_REQ_MESSAGE */ - struct register_reject_message reg_rej; - struct reset_message reset; - /* no data for KEEP_ALIVE_ACK_MESSAGE */ - struct open_receive_channel_message open_receive_channel; - struct close_receive_channel_message close_receive_channel; - struct soft_key_template_res_message soft_key_template; - struct soft_key_set_res_message soft_key_set; - struct select_soft_keys_message select_soft_keys; - struct call_state_message call_state; - struct display_prompt_status_message display_prompt_status; - struct clear_prompt_status_message clear_prompt_status; - struct activate_call_plane_message activate_call_plane; - struct unregister_ack_message unregister_ack; - struct back_space_req_message back_space_req; - struct dialed_number_message dialed_number; - /* see field "data" for USER_TO_DEVICE_DATA_MESSAGE */ - struct feature_stat_res_message feature_res; - struct display_pri_notify_message display_pri_notify; - struct service_url_stat_res_message service_url_res; - /* see field "extended_data" for USER_TO_DEVICE_DATA_VERSION1_MESSAGE */ + struct register_message reg; + struct port_message port; + struct keypad_button_message keypad_button; + struct enbloc_call_message enbloc_call; + struct stimulus_message stimulus; + struct off_hook_message off_hook; + struct on_hook_message on_hook; + struct forward_stat_req_message forward_stat_req; + struct speed_dial_stat_req_message speed_dial_req; + struct line_stat_req_message line_req; + /* no data for CONFIG_STAT_REQ_MESSAGE */ + /* no data for TIME_DATE_REQ_MESSAGE */ + /* no data for BUTTON_TEMPLATE_REQ_MESSAGE */ + /* no data for VERSION_REQ_MESSAGE */ + struct capabilities_res_message cap_res; + struct alarm_message alarm; + struct open_receive_channel_ack_message open_receive_channel_ack; + /* no data for SOFT_KEY_SET_REQ_MESSAGE */ + struct soft_key_event_message soft_key_event; + /* no data for UNREGISTER_MESSAGE */ + /* no data for SOFT_KEY_TEMPLATE_REQ_MESSAGE */ + struct headset_status_message headset_status; + struct register_available_lines_message reg_lines; + /* see field "data" for DEVICE_TO_USER_DATA_MESSAGE */ + /* see field "data" for DEVICE_TO_USER_DATA_RESPONSE_MESSAGE */ + struct service_url_stat_req_message service_url_req; + struct feature_stat_req_message feature_req; + /* see field "extended_data" for DEVICE_TO_USER_DATA_VERSION1_MESSAGE */ + /* see field "extended_data" for DEVICE_TO_USER_DATA_RESPONSE_VERSION1_MESSAGE */ + struct register_ack_message reg_ack; + struct start_tone_message start_tone; + struct stop_tone_message stop_tone; + struct set_ringer_message ringer; + struct set_lamp_message lamp; + struct set_speaker_mode_message speaker_mode; + struct start_media_transmission_message start_media; + struct stop_media_transmission_message stop_media; + struct call_info_message call_info; + struct forward_stat_message forward_stat; + struct speed_dial_stat_res_message speed_dial_res; + struct line_stat_res_message line_res; + struct config_stat_res_message config_res; + struct define_time_date_message define_time_date; + struct button_template_message button_template; + struct version_message version; + /* no data for CAPABILITIES_REQ_MESSAGE */ + struct register_reject_message reg_rej; + struct reset_message reset; + /* no data for KEEP_ALIVE_ACK_MESSAGE */ + struct open_receive_channel_message open_receive_channel; + struct close_receive_channel_message close_receive_channel; + struct soft_key_template_res_message soft_key_template; + struct soft_key_set_res_message soft_key_set; + struct select_soft_keys_message select_soft_keys; + struct call_state_message call_state; + struct display_prompt_status_message display_prompt_status; + struct clear_prompt_status_message clear_prompt_status; + struct activate_call_plane_message activate_call_plane; + struct unregister_ack_message unregister_ack; + struct back_space_req_message back_space_req; + struct dialed_number_message dialed_number; + /* see field "data" for USER_TO_DEVICE_DATA_MESSAGE */ + struct feature_stat_res_message feature_res; + struct display_pri_notify_message display_pri_notify; + struct service_url_stat_res_message service_url_res; + /* see field "extended_data" for USER_TO_DEVICE_DATA_VERSION1_MESSAGE */ struct data_message data; struct extended_data_message extended_data; - uint16_t as_uint16; - char as_char[1]; + uint16_t as_uint16; + char as_char[1]; }; /* diff --git a/src/mod/endpoints/mod_skinny/skinny_server.c b/src/mod/endpoints/mod_skinny/skinny_server.c index e7c761dfca..dac75facd7 100644 --- a/src/mod/endpoints/mod_skinny/skinny_server.c +++ b/src/mod/endpoints/mod_skinny/skinny_server.c @@ -555,6 +555,7 @@ int skinny_ring_lines_callback(void *pArg, int argc, char **argv, char **columnN skinny_session_send_call_info(helper->tech_pvt->session, listener, line_instance); send_set_lamp(listener, SKINNY_BUTTON_LINE, line_instance, SKINNY_LAMP_BLINK); send_set_ringer(listener, SKINNY_RING_INSIDE, SKINNY_RING_FOREVER, 0, helper->tech_pvt->call_id); + switch_channel_mark_ring_ready(channel); } return 0; } @@ -1006,6 +1007,10 @@ switch_status_t skinny_handle_register(listener_t *listener, skinny_message_t *r } if ((xbuttons = switch_xml_child(xskinny, "buttons"))) { uint32_t line_instance = 1; + char *network_ip = inet_ntoa(request->data.reg.ip); + int network_port = 0; + char network_port_c[6]; + snprintf(network_port_c, sizeof(network_port_c), "%d", network_port); for (xbutton = switch_xml_child(xbuttons, "button"); xbutton; xbutton = xbutton->next) { uint32_t position = atoi(switch_xml_attr_soft(xbutton, "position")); uint32_t type = skinny_str2button(switch_xml_attr_soft(xbutton, "type")); @@ -1031,8 +1036,14 @@ switch_status_t skinny_handle_register(listener_t *listener, skinny_message_t *r label, value, caller_name, ring_on_idle, ring_on_active, busy_trigger, forward_all, forward_busy, forward_noanswer, noanswer_duration))) { + char *token, *url; skinny_execute_sql(profile, sql, profile->sql_mutex); switch_safe_free(sql); + token = switch_mprintf("skinny/%q/%q/%q:%d", profile->name, value, request->data.reg.device_name, request->data.reg.instance); + url = switch_mprintf("skinny/%q/%q", profile->name, value); + switch_core_add_registration(value, profile->domain, token, url, 0, network_ip, network_port_c, "tcp"); + switch_safe_free(token); + switch_safe_free(url); } if (line_instance == 1) { switch_event_t *message_query_event = NULL; @@ -1318,6 +1329,22 @@ switch_status_t skinny_handle_on_hook_message(listener_t *listener, skinny_messa return status; } +switch_status_t skinny_handle_forward_stat_req_message(listener_t *listener, skinny_message_t *request) +{ + skinny_message_t *message; + + skinny_check_data_length(request, sizeof(request->data.forward_stat_req)); + + message = switch_core_alloc(listener->pool, 12+sizeof(message->data.forward_stat)); + message->type = FORWARD_STAT_MESSAGE; + message->length = 4 + sizeof(message->data.forward_stat); + + message->data.forward_stat.line_instance = request->data.forward_stat_req.line_instance; + + skinny_send_reply(listener, message); + + return SWITCH_STATUS_SUCCESS; +} switch_status_t skinny_handle_speed_dial_stat_request(listener_t *listener, skinny_message_t *request) { @@ -1649,12 +1676,12 @@ switch_status_t skinny_handle_open_receive_channel_ack_message(listener_t *liste goto end; } + tech_pvt->local_sdp_audio_ip = listener->local_ip; /* Request a local port from the core's allocator */ - if (!(tech_pvt->local_sdp_audio_port = switch_rtp_request_port(listener->profile->ip))) { + if (!(tech_pvt->local_sdp_audio_port = switch_rtp_request_port(tech_pvt->local_sdp_audio_ip))) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_CRIT, "No RTP ports available!\n"); return SWITCH_STATUS_FALSE; } - tech_pvt->local_sdp_audio_ip = switch_core_strdup(switch_core_session_get_pool(session), listener->profile->ip); tech_pvt->remote_sdp_audio_ip = inet_ntoa(request->data.open_receive_channel_ack.ip); tech_pvt->remote_sdp_audio_port = request->data.open_receive_channel_ack.port; @@ -2035,6 +2062,8 @@ switch_status_t skinny_handle_request(listener_t *listener, skinny_message_t *re return skinny_handle_off_hook_message(listener, request); case ON_HOOK_MESSAGE: return skinny_handle_on_hook_message(listener, request); + case FORWARD_STAT_REQ_MESSAGE: + return skinny_handle_forward_stat_req_message(listener, request); case SPEED_DIAL_STAT_REQ_MESSAGE: return skinny_handle_speed_dial_stat_request(listener, request); case LINE_STAT_REQ_MESSAGE: diff --git a/src/mod/endpoints/mod_skinny/skinny_tables.c b/src/mod/endpoints/mod_skinny/skinny_tables.c index 466a70538d..e8e56568b3 100644 --- a/src/mod/endpoints/mod_skinny/skinny_tables.c +++ b/src/mod/endpoints/mod_skinny/skinny_tables.c @@ -35,73 +35,75 @@ /* Translation tables */ struct skinny_table SKINNY_MESSAGE_TYPES[] = { - {"KeepAliveMessage", KEEP_ALIVE_MESSAGE}, - {"RegisterMessage", REGISTER_MESSAGE}, - {"PortMessage", PORT_MESSAGE}, - {"KeypadButtonMessage", KEYPAD_BUTTON_MESSAGE}, - {"EnblocCallMessage", ENBLOC_CALL_MESSAGE}, - {"StimulusMessage", STIMULUS_MESSAGE}, - {"OffHookMessage", OFF_HOOK_MESSAGE}, - {"OnHookMessage", ON_HOOK_MESSAGE}, - {"SpeedDialStatReqMessage", SPEED_DIAL_STAT_REQ_MESSAGE}, - {"LineStatReqMessage", LINE_STAT_REQ_MESSAGE}, - {"ConfigStatReqMessage", CONFIG_STAT_REQ_MESSAGE}, - {"TimeDateReqMessage", TIME_DATE_REQ_MESSAGE}, - {"ButtonTemplateReqMessage", BUTTON_TEMPLATE_REQ_MESSAGE}, - {"VersionReqMessage", VERSION_REQ_MESSAGE}, - {"CapabilitiesReqMessage", CAPABILITIES_RES_MESSAGE}, - {"AlarmMessage", ALARM_MESSAGE}, - {"OpenReceiveChannelAckMessage", OPEN_RECEIVE_CHANNEL_ACK_MESSAGE}, - {"SoftKeySetReqMessage", SOFT_KEY_SET_REQ_MESSAGE}, - {"SoftKeyEventMessage", SOFT_KEY_EVENT_MESSAGE}, - {"UnregisterMessage", UNREGISTER_MESSAGE}, - {"SoftKeyTemplateReqMessage", SOFT_KEY_TEMPLATE_REQ_MESSAGE}, - {"HeadsetStatusMessage", HEADSET_STATUS_MESSAGE}, - {"RegisterAvailableLinesMessage", REGISTER_AVAILABLE_LINES_MESSAGE}, - {"DeviceToUserDataMessage", DEVICE_TO_USER_DATA_MESSAGE}, - {"DeviceToUserDataResponseMessage", DEVICE_TO_USER_DATA_RESPONSE_MESSAGE}, - {"ServiceUrlStatReqMessage", SERVICE_URL_STAT_REQ_MESSAGE}, - {"FeatureStatReqMessage", FEATURE_STAT_REQ_MESSAGE}, - {"DeviceToUserDataVersion1Message", DEVICE_TO_USER_DATA_VERSION1_MESSAGE}, - {"DeviceToUserDataResponseVersion1Message", DEVICE_TO_USER_DATA_RESPONSE_VERSION1_MESSAGE}, - {"RegisterAckMessage", REGISTER_ACK_MESSAGE}, - {"StartToneMessage", START_TONE_MESSAGE}, - {"StopToneMessage", STOP_TONE_MESSAGE}, - {"SetRingerMessage", SET_RINGER_MESSAGE}, - {"SetLampMessage", SET_LAMP_MESSAGE}, - {"SetSpeakerModeMessage", SET_SPEAKER_MODE_MESSAGE}, - {"StartMediaTransmissionMessage", START_MEDIA_TRANSMISSION_MESSAGE}, - {"StopMediaTransmissionMessage", STOP_MEDIA_TRANSMISSION_MESSAGE}, - {"CallInfoMessage", CALL_INFO_MESSAGE}, - {"SpeedDialStatResMessage", SPEED_DIAL_STAT_RES_MESSAGE}, - {"LineStatResMessage", LINE_STAT_RES_MESSAGE}, - {"ConfigStatResMessage", CONFIG_STAT_RES_MESSAGE}, - {"DefineTimeDateMessage", DEFINE_TIME_DATE_MESSAGE}, - {"ButtonTemplateResMessage", BUTTON_TEMPLATE_RES_MESSAGE}, - {"VersionMessage", VERSION_MESSAGE}, - {"CapabilitiesReqMessage", CAPABILITIES_REQ_MESSAGE}, - {"RegisterRejectMessage", REGISTER_REJECT_MESSAGE}, - {"ResetMessage", RESET_MESSAGE}, - {"KeepAliveAckMessage", KEEP_ALIVE_ACK_MESSAGE}, - {"OpenReceiveChannelMessage", OPEN_RECEIVE_CHANNEL_MESSAGE}, - {"CloseReceiveChannelMessage", CLOSE_RECEIVE_CHANNEL_MESSAGE}, - {"SoftKeyTemplateResMessage", SOFT_KEY_TEMPLATE_RES_MESSAGE}, - {"SoftKeySetResMessage", SOFT_KEY_SET_RES_MESSAGE}, - {"SelectSoftKeysMessage", SELECT_SOFT_KEYS_MESSAGE}, - {"CallStateMessage", CALL_STATE_MESSAGE}, - {"DisplayPromptStatusMessage", DISPLAY_PROMPT_STATUS_MESSAGE}, - {"ClearPromptStatusMessage", CLEAR_PROMPT_STATUS_MESSAGE}, - {"ActivateCallPlaneMessage", ACTIVATE_CALL_PLANE_MESSAGE}, - {"UnregisterAckMessage", UNREGISTER_ACK_MESSAGE}, - {"BackSpaceReqMessage", BACK_SPACE_REQ_MESSAGE}, - {"DialedNumberMessage", DIALED_NUMBER_MESSAGE}, - {"UserToDeviceDataMessage", USER_TO_DEVICE_DATA_MESSAGE}, - {"FeatureResMessage", FEATURE_STAT_RES_MESSAGE}, - {"DisplayPriNotifyMessage", DISPLAY_PRI_NOTIFY_MESSAGE}, - {"ServiceUrlStatMessage", SERVICE_URL_STAT_RES_MESSAGE}, - {"UserToDeviceDataVersion1Message", USER_TO_DEVICE_DATA_VERSION1_MESSAGE}, - {"XMLAlarmMessage", XML_ALARM_MESSAGE}, - {NULL, 0} + {"KeepAliveMessage", KEEP_ALIVE_MESSAGE}, + {"RegisterMessage", REGISTER_MESSAGE}, + {"PortMessage", PORT_MESSAGE}, + {"KeypadButtonMessage", KEYPAD_BUTTON_MESSAGE}, + {"EnblocCallMessage", ENBLOC_CALL_MESSAGE}, + {"StimulusMessage", STIMULUS_MESSAGE}, + {"OffHookMessage", OFF_HOOK_MESSAGE}, + {"OnHookMessage", ON_HOOK_MESSAGE}, + {"ForwardStatReqMessage", FORWARD_STAT_REQ_MESSAGE}, + {"SpeedDialStatReqMessage", SPEED_DIAL_STAT_REQ_MESSAGE}, + {"LineStatReqMessage", LINE_STAT_REQ_MESSAGE}, + {"ConfigStatReqMessage", CONFIG_STAT_REQ_MESSAGE}, + {"TimeDateReqMessage", TIME_DATE_REQ_MESSAGE}, + {"ButtonTemplateReqMessage", BUTTON_TEMPLATE_REQ_MESSAGE}, + {"VersionReqMessage", VERSION_REQ_MESSAGE}, + {"CapabilitiesReqMessage", CAPABILITIES_RES_MESSAGE}, + {"AlarmMessage", ALARM_MESSAGE}, + {"OpenReceiveChannelAckMessage", OPEN_RECEIVE_CHANNEL_ACK_MESSAGE}, + {"SoftKeySetReqMessage", SOFT_KEY_SET_REQ_MESSAGE}, + {"SoftKeyEventMessage", SOFT_KEY_EVENT_MESSAGE}, + {"UnregisterMessage", UNREGISTER_MESSAGE}, + {"SoftKeyTemplateReqMessage", SOFT_KEY_TEMPLATE_REQ_MESSAGE}, + {"HeadsetStatusMessage", HEADSET_STATUS_MESSAGE}, + {"RegisterAvailableLinesMessage", REGISTER_AVAILABLE_LINES_MESSAGE}, + {"DeviceToUserDataMessage", DEVICE_TO_USER_DATA_MESSAGE}, + {"DeviceToUserDataResponseMessage", DEVICE_TO_USER_DATA_RESPONSE_MESSAGE}, + {"ServiceUrlStatReqMessage", SERVICE_URL_STAT_REQ_MESSAGE}, + {"FeatureStatReqMessage", FEATURE_STAT_REQ_MESSAGE}, + {"DeviceToUserDataVersion1Message", DEVICE_TO_USER_DATA_VERSION1_MESSAGE}, + {"DeviceToUserDataResponseVersion1Message", DEVICE_TO_USER_DATA_RESPONSE_VERSION1_MESSAGE}, + {"RegisterAckMessage", REGISTER_ACK_MESSAGE}, + {"StartToneMessage", START_TONE_MESSAGE}, + {"StopToneMessage", STOP_TONE_MESSAGE}, + {"SetRingerMessage", SET_RINGER_MESSAGE}, + {"SetLampMessage", SET_LAMP_MESSAGE}, + {"SetSpeakerModeMessage", SET_SPEAKER_MODE_MESSAGE}, + {"StartMediaTransmissionMessage", START_MEDIA_TRANSMISSION_MESSAGE}, + {"StopMediaTransmissionMessage", STOP_MEDIA_TRANSMISSION_MESSAGE}, + {"CallInfoMessage", CALL_INFO_MESSAGE}, + {"ForwardStatMessage", FORWARD_STAT_MESSAGE}, + {"SpeedDialStatResMessage", SPEED_DIAL_STAT_RES_MESSAGE}, + {"LineStatResMessage", LINE_STAT_RES_MESSAGE}, + {"ConfigStatResMessage", CONFIG_STAT_RES_MESSAGE}, + {"DefineTimeDateMessage", DEFINE_TIME_DATE_MESSAGE}, + {"ButtonTemplateResMessage", BUTTON_TEMPLATE_RES_MESSAGE}, + {"VersionMessage", VERSION_MESSAGE}, + {"CapabilitiesReqMessage", CAPABILITIES_REQ_MESSAGE}, + {"RegisterRejectMessage", REGISTER_REJECT_MESSAGE}, + {"ResetMessage", RESET_MESSAGE}, + {"KeepAliveAckMessage", KEEP_ALIVE_ACK_MESSAGE}, + {"OpenReceiveChannelMessage", OPEN_RECEIVE_CHANNEL_MESSAGE}, + {"CloseReceiveChannelMessage", CLOSE_RECEIVE_CHANNEL_MESSAGE}, + {"SoftKeyTemplateResMessage", SOFT_KEY_TEMPLATE_RES_MESSAGE}, + {"SoftKeySetResMessage", SOFT_KEY_SET_RES_MESSAGE}, + {"SelectSoftKeysMessage", SELECT_SOFT_KEYS_MESSAGE}, + {"CallStateMessage", CALL_STATE_MESSAGE}, + {"DisplayPromptStatusMessage", DISPLAY_PROMPT_STATUS_MESSAGE}, + {"ClearPromptStatusMessage", CLEAR_PROMPT_STATUS_MESSAGE}, + {"ActivateCallPlaneMessage", ACTIVATE_CALL_PLANE_MESSAGE}, + {"UnregisterAckMessage", UNREGISTER_ACK_MESSAGE}, + {"BackSpaceReqMessage", BACK_SPACE_REQ_MESSAGE}, + {"DialedNumberMessage", DIALED_NUMBER_MESSAGE}, + {"UserToDeviceDataMessage", USER_TO_DEVICE_DATA_MESSAGE}, + {"FeatureResMessage", FEATURE_STAT_RES_MESSAGE}, + {"DisplayPriNotifyMessage", DISPLAY_PRI_NOTIFY_MESSAGE}, + {"ServiceUrlStatMessage", SERVICE_URL_STAT_RES_MESSAGE}, + {"UserToDeviceDataVersion1Message", USER_TO_DEVICE_DATA_VERSION1_MESSAGE}, + {"XMLAlarmMessage", XML_ALARM_MESSAGE}, + {NULL, 0} }; SKINNY_DECLARE_ID2STR(skinny_message_type2str, SKINNY_MESSAGE_TYPES, "UnknownMessage") SKINNY_DECLARE_STR2ID(skinny_str2message_type, SKINNY_MESSAGE_TYPES, -1) @@ -216,6 +218,7 @@ struct skinny_table SKINNY_KEY_SETS[] = { {"KeySetConnectedWithConference", SKINNY_KEY_SET_CONNECTED_WITH_CONFERENCE}, {"KeySetRingOut", SKINNY_KEY_SET_RING_OUT}, {"KeySetOffHookWithFeatures", SKINNY_KEY_SET_OFF_HOOK_WITH_FEATURES}, + {"KeySetInUseHint", SKINNY_KEY_SET_IN_USE_HINT}, {NULL, 0} }; SKINNY_DECLARE_ID2STR(skinny_soft_key_set2str, SKINNY_KEY_SETS, "UNKNOWN_SOFT_KEY_SET") diff --git a/src/mod/endpoints/mod_skinny/skinny_tables.h b/src/mod/endpoints/mod_skinny/skinny_tables.h index bc92f9f4bf..00ddf0c74d 100644 --- a/src/mod/endpoints/mod_skinny/skinny_tables.h +++ b/src/mod/endpoints/mod_skinny/skinny_tables.h @@ -87,7 +87,7 @@ uint32_t func(const char *str)\ } -extern struct skinny_table SKINNY_MESSAGE_TYPES[67]; +extern struct skinny_table SKINNY_MESSAGE_TYPES[69]; const char *skinny_message_type2str(uint32_t id); uint32_t skinny_str2message_type(const char *str); #define SKINNY_PUSH_MESSAGE_TYPES SKINNY_DECLARE_PUSH_MATCH(SKINNY_MESSAGE_TYPES) @@ -210,8 +210,9 @@ enum skinny_key_set { SKINNY_KEY_SET_CONNECTED_WITH_CONFERENCE = 7, SKINNY_KEY_SET_RING_OUT = 8, SKINNY_KEY_SET_OFF_HOOK_WITH_FEATURES = 9, + SKINNY_KEY_SET_IN_USE_HINT = 10, }; -extern struct skinny_table SKINNY_KEY_SETS[11]; +extern struct skinny_table SKINNY_KEY_SETS[12]; const char *skinny_soft_key_set2str(uint32_t id); uint32_t skinny_str2soft_key_set(const char *str); #define SKINNY_PUSH_SOFT_KEY_SETS SKINNY_DECLARE_PUSH_MATCH(SKINNY_KEY_SETS) diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index 4853dff3bf..0921f1f313 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -1349,10 +1349,10 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi case SWITCH_MESSAGE_INDICATE_JITTER_BUFFER: { if (switch_rtp_ready(tech_pvt->rtp_session)) { - int len, maxlen = 0, qlen = 0, maxqlen = 50; + int len, maxlen = 0, qlen = 0, maxqlen = 50, max_drift = 0; if (msg->string_arg) { - char *p; + char *p, *q; const char *s; if (!strcasecmp(msg->string_arg, "pause")) { @@ -1379,6 +1379,10 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi if ((p = strchr(msg->string_arg, ':'))) { p++; maxlen = atol(p); + if ((q = strchr(p, ':'))) { + q++; + max_drift = abs(atol(q)); + } } } @@ -1391,9 +1395,10 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi if (qlen) { if (switch_rtp_activate_jitter_buffer(tech_pvt->rtp_session, qlen, maxqlen, tech_pvt->read_impl.samples_per_packet, - tech_pvt->read_impl.samples_per_second) == SWITCH_STATUS_SUCCESS) { + tech_pvt->read_impl.samples_per_second, max_drift) == SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), - SWITCH_LOG_DEBUG, "Setting Jitterbuffer to %dms (%d frames) (%d max frames)\n", len, qlen, maxqlen); + SWITCH_LOG_DEBUG, "Setting Jitterbuffer to %dms (%d frames) (%d max frames) (%d max drift)\n", + len, qlen, maxqlen, max_drift); switch_channel_set_flag(tech_pvt->channel, CF_JITTERBUFFER); } else { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), @@ -1439,10 +1444,13 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi case SWITCH_MESSAGE_INDICATE_BRIDGE: { + const char *var = switch_channel_get_variable(tech_pvt->channel, "sip_jitter_buffer_during_bridge"); + sofia_glue_tech_track(tech_pvt->profile, session); + sofia_glue_tech_simplify(tech_pvt); - if (switch_rtp_ready(tech_pvt->rtp_session)) { + if (switch_false(var) && switch_rtp_ready(tech_pvt->rtp_session)) { const char *val; int ok = 0; @@ -1477,6 +1485,8 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi const char *val; int ok = 0; + sofia_glue_tech_track(tech_pvt->profile, session); + if (switch_channel_test_flag(tech_pvt->channel, CF_JITTERBUFFER)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s RESUME Jitterbuffer\n", switch_channel_get_name(channel)); @@ -3513,7 +3523,7 @@ SWITCH_STANDARD_API(sofia_contact_function) profile = sofia_glue_find_profile(profile_name); } - if (!profile) { + if (!profile && !zstr(domain)) { profile = sofia_glue_find_profile(domain); } } @@ -4587,17 +4597,42 @@ static void general_event_handler(switch_event_t *event) case SWITCH_EVENT_TRAP: { const char *cond = switch_event_get_header(event, "condition"); + switch_hash_index_t *hi; + const void *var; + void *val; + sofia_profile_t *profile; + if (zstr(cond)) { + cond = ""; + } - if (cond && !strcmp(cond, "network-address-change") && mod_sofia_globals.auto_restart) { + if (!strcmp(cond, "network-external-address-change") && mod_sofia_globals.auto_restart) { + const char *old_ip4 = switch_event_get_header_nil(event, "network-external-address-previous-v4"); + const char *new_ip4 = switch_event_get_header_nil(event, "network-external-address-change-v4"); + + switch_mutex_lock(mod_sofia_globals.hash_mutex); + if (mod_sofia_globals.profile_hash && !zstr(old_ip4) && !zstr(new_ip4)) { + for (hi = switch_hash_first(NULL, mod_sofia_globals.profile_hash); hi; hi = switch_hash_next(hi)) { + switch_hash_this(hi, &var, NULL, &val); + + if ((profile = (sofia_profile_t *) val)) { + if (!zstr(profile->extsipip) && !strcmp(profile->extsipip, old_ip4)) { + profile->extsipip = switch_core_strdup(profile->pool, new_ip4); + } + + if (!zstr(profile->extrtpip) && !strcmp(profile->extrtpip, old_ip4)) { + profile->extrtpip = switch_core_strdup(profile->pool, new_ip4); + } + } + } + } + switch_mutex_unlock(mod_sofia_globals.hash_mutex); + sofia_glue_restart_all_profiles(); + } else if (!strcmp(cond, "network-address-change") && mod_sofia_globals.auto_restart) { const char *old_ip4 = switch_event_get_header_nil(event, "network-address-previous-v4"); const char *new_ip4 = switch_event_get_header_nil(event, "network-address-change-v4"); const char *old_ip6 = switch_event_get_header_nil(event, "network-address-previous-v6"); const char *new_ip6 = switch_event_get_header_nil(event, "network-address-change-v6"); - switch_hash_index_t *hi; - const void *var; - void *val; - sofia_profile_t *profile; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "EVENT_TRAP: IP change detected\n"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "IP change detected [%s]->[%s] [%s]->[%s]\n", old_ip4, new_ip4, old_ip6, new_ip6); diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 8a3d1b10f6..fac089d12c 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -864,7 +864,6 @@ void sofia_event_callback(nua_event_t event, case nua_r_unsubscribe: case nua_r_publish: case nua_i_cancel: - case nua_r_cancel: case nua_i_error: case nua_i_active: case nua_i_terminated: @@ -872,6 +871,13 @@ void sofia_event_callback(nua_event_t event, case nua_i_prack: case nua_r_prack: break; + case nua_r_cancel: + { + if (status > 299 && nh) { + nua_handle_destroy(nh); + } + } + break; case nua_i_ack: { if (channel && sip) { @@ -2135,7 +2141,7 @@ static void parse_gateways(sofia_profile_t *profile, switch_xml_t gateways_tag) register_transport = (char *) sofia_glue_transport2str(gateway->register_transport); - if (contact_params) { + if (! zstr(contact_params)) { if (*contact_params == ';') { params = switch_core_sprintf(gateway->pool, "%s;transport=%s;gw=%s", contact_params, register_transport, gateway->name); } else { diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 01a70f32b6..a76467f5d8 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -3166,12 +3166,16 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f if ((val = switch_channel_get_variable(tech_pvt->channel, "jitterbuffer_msec")) || (val = tech_pvt->profile->jb_msec)) { int jb_msec = atoi(val); - int maxlen = 0; - char *p; - + int maxlen = 0, max_drift = 0; + char *p, *q; + if ((p = strchr(val, ':'))) { p++; maxlen = atoi(p); + if ((q = strchr(p, ':'))) { + q++; + max_drift = abs(atoi(q)); + } } if (jb_msec < 20 || jb_msec > 10000) { @@ -3188,7 +3192,7 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f if (switch_rtp_activate_jitter_buffer(tech_pvt->rtp_session, qlen, maxqlen, tech_pvt->read_impl.samples_per_packet, - tech_pvt->read_impl.samples_per_second) == SWITCH_STATUS_SUCCESS) { + tech_pvt->read_impl.samples_per_second, max_drift) == SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Setting Jitterbuffer to %dms (%d frames)\n", jb_msec, qlen); switch_channel_set_flag(tech_pvt->channel, CF_JITTERBUFFER); @@ -3238,7 +3242,9 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f } if (tech_pvt->audio_recv_pt != tech_pvt->agreed_pt) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_CRIT, "Set audio receive payload to %u\n", tech_pvt->audio_recv_pt); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, + "%s Set audio receive payload to %u\n", switch_channel_get_name(tech_pvt->channel), tech_pvt->audio_recv_pt); + switch_rtp_set_recv_pt(tech_pvt->rtp_session, tech_pvt->audio_recv_pt); } @@ -3423,8 +3429,8 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f if (tech_pvt->video_recv_pt != tech_pvt->video_agreed_pt) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, - "Set video receive payload to %u\n", tech_pvt->video_recv_pt); - switch_rtp_set_recv_pt(tech_pvt->rtp_session, tech_pvt->video_recv_pt); + "%s Set video receive payload to %u\n", switch_channel_get_name(tech_pvt->channel), tech_pvt->video_recv_pt); + switch_rtp_set_recv_pt(tech_pvt->video_rtp_session, tech_pvt->video_recv_pt); } switch_channel_set_variable_printf(tech_pvt->channel, "sip_use_video_pt", "%d", tech_pvt->video_agreed_pt); @@ -3484,6 +3490,59 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f } +static void add_audio_codec(sdp_rtpmap_t *map, int ptime, char *buf, switch_size_t buflen) +{ + int codec_ms = ptime; + uint32_t map_bit_rate = 0; + char ptstr[20] = ""; + char ratestr[20] = ""; + char bitstr[20] = ""; + switch_codec_fmtp_t codec_fmtp = { 0 }; + + if (!codec_ms) { + codec_ms = switch_default_ptime(map->rm_encoding, map->rm_pt); + } + + map_bit_rate = switch_known_bitrate(map->rm_pt); + + if (!ptime && !strcasecmp(map->rm_encoding, "g723")) { + ptime = codec_ms = 30; + } + + if (zstr(map->rm_fmtp)) { + if (!strcasecmp(map->rm_encoding, "ilbc")) { + ptime = codec_ms = 30; + map_bit_rate = 13330; + } + } else { + if ((switch_core_codec_parse_fmtp(map->rm_encoding, map->rm_fmtp, map->rm_rate, &codec_fmtp)) == SWITCH_STATUS_SUCCESS) { + if (codec_fmtp.bits_per_second) { + map_bit_rate = codec_fmtp.bits_per_second; + } + if (codec_fmtp.microseconds_per_packet) { + codec_ms = (codec_fmtp.microseconds_per_packet / 1000); + } + } + } + + if (map->rm_rate) { + switch_snprintf(ratestr, sizeof(ratestr), "@%uh", (unsigned int) map->rm_rate); + } + + if (codec_ms) { + switch_snprintf(ptstr, sizeof(ptstr), "@%di", codec_ms); + } + + if (map_bit_rate) { + switch_snprintf(bitstr, sizeof(bitstr), "@%db", map_bit_rate); + } + + switch_snprintf(buf + strlen(buf), buflen - strlen(buf), ",%s%s%s%s", map->rm_encoding, ratestr, ptstr, bitstr); + +} + + + void sofia_glue_set_r_sdp_codec_string(switch_core_session_t *session, const char *codec_string, sdp_session_t *sdp) { char buf[1024] = { 0 }; @@ -3500,7 +3559,13 @@ void sofia_glue_set_r_sdp_codec_string(switch_core_session_t *session, const cha const switch_codec_implementation_t *codecs[SWITCH_MAX_CODECS] = { 0 }; switch_channel_t *channel = switch_core_session_get_channel(session); private_object_t *tech_pvt = switch_core_session_get_private(session); + int prefer_sdp = 0; + const char *var; + if ((var = switch_channel_get_variable(channel, "ep_codec_prefer_sdp")) && switch_true(var)) { + prefer_sdp = 1; + } + if (!zstr(codec_string)) { char *tmp_codec_string; if ((tmp_codec_string = strdup(codec_string))) { @@ -3551,78 +3616,62 @@ void sofia_glue_set_r_sdp_codec_string(switch_core_session_t *session, const cha break; } - for (i = 0; i < num_codecs; i++) { - const switch_codec_implementation_t *imp = codecs[i]; - if (imp->codec_type != SWITCH_CODEC_TYPE_AUDIO || imp->ianacode > 127 || already_did[imp->ianacode]) { - continue; - } + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND || prefer_sdp) { for (map = m->m_rtpmaps; map; map = map->rm_next) { if (map->rm_pt > 127 || already_did[map->rm_pt]) { continue; } - if ((zstr(map->rm_encoding) || (tech_pvt->profile->ndlb & PFLAG_NDLB_ALLOW_BAD_IANANAME)) && map->rm_pt < 96) { - match = (map->rm_pt == imp->ianacode) ? 1 : 0; - } else { - if (map->rm_encoding) { - match = strcasecmp(map->rm_encoding, imp->iananame) ? 0 : 1; + for (i = 0; i < num_codecs; i++) { + const switch_codec_implementation_t *imp = codecs[i]; + + if ((zstr(map->rm_encoding) || (tech_pvt->profile->ndlb & PFLAG_NDLB_ALLOW_BAD_IANANAME)) && map->rm_pt < 96) { + match = (map->rm_pt == imp->ianacode) ? 1 : 0; } else { - match = 0; + if (map->rm_encoding) { + match = strcasecmp(map->rm_encoding, imp->iananame) ? 0 : 1; + } else { + match = 0; + } } + + if (match) { + add_audio_codec(map, ptime, buf, sizeof(buf)); + break; + } + } + } - if (match) { - int codec_ms = ptime; - uint32_t map_bit_rate = 0; - char ptstr[20] = ""; - char ratestr[20] = ""; - char bitstr[20] = ""; - switch_codec_fmtp_t codec_fmtp = { 0 }; - - if (!codec_ms) { - codec_ms = switch_default_ptime(map->rm_encoding, map->rm_pt); + } else { + for (i = 0; i < num_codecs; i++) { + const switch_codec_implementation_t *imp = codecs[i]; + if (imp->codec_type != SWITCH_CODEC_TYPE_AUDIO || imp->ianacode > 127 || already_did[imp->ianacode]) { + continue; + } + for (map = m->m_rtpmaps; map; map = map->rm_next) { + if (map->rm_pt > 127 || already_did[map->rm_pt]) { + continue; } - map_bit_rate = switch_known_bitrate(map->rm_pt); - - if (!ptime && !strcasecmp(map->rm_encoding, "g723")) { - ptime = codec_ms = 30; - } - - if (zstr(map->rm_fmtp)) { - if (!strcasecmp(map->rm_encoding, "ilbc")) { - ptime = codec_ms = 30; - map_bit_rate = 13330; - } + if ((zstr(map->rm_encoding) || (tech_pvt->profile->ndlb & PFLAG_NDLB_ALLOW_BAD_IANANAME)) && map->rm_pt < 96) { + match = (map->rm_pt == imp->ianacode) ? 1 : 0; } else { - if ((switch_core_codec_parse_fmtp(map->rm_encoding, map->rm_fmtp, map->rm_rate, &codec_fmtp)) == SWITCH_STATUS_SUCCESS) { - if (codec_fmtp.bits_per_second) { - map_bit_rate = codec_fmtp.bits_per_second; - } - if (codec_fmtp.microseconds_per_packet) { - codec_ms = (codec_fmtp.microseconds_per_packet / 1000); - } + if (map->rm_encoding) { + match = strcasecmp(map->rm_encoding, imp->iananame) ? 0 : 1; + } else { + match = 0; } } - if (map->rm_rate) { - switch_snprintf(ratestr, sizeof(ratestr), "@%uh", (unsigned int) map->rm_rate); + if (match) { + add_audio_codec(map, ptime, buf, sizeof(buf)); + break; } - - if (codec_ms) { - switch_snprintf(ptstr, sizeof(ptstr), "@%di", codec_ms); - } - - if (map_bit_rate) { - switch_snprintf(bitstr, sizeof(bitstr), "@%db", map_bit_rate); - } - - switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ",%s%s%s%s", map->rm_encoding, ratestr, ptstr, bitstr); - - break; } } } + } else if (m->m_type == sdp_media_video && m->m_port) { connection = sdp->sdp_connection; if (m->m_connections) { @@ -3814,6 +3863,7 @@ static switch_t38_options_t *tech_process_udptl(private_object_t *tech_pvt, sdp_ { switch_t38_options_t *t38_options = switch_channel_get_private(tech_pvt->channel, "t38_options"); sdp_attribute_t *attr; + const char *var; if (!t38_options) { t38_options = switch_core_session_alloc(tech_pvt->session, sizeof(switch_t38_options_t)); @@ -3893,6 +3943,21 @@ static switch_t38_options_t *tech_process_udptl(private_object_t *tech_pvt, sdp_ switch_channel_set_private(tech_pvt->channel, "t38_options", t38_options); switch_channel_set_app_flag_key("T38", tech_pvt->channel, CF_APP_T38); + if ((var = switch_channel_get_variable(tech_pvt->channel, "sip_execute_on_image"))) { + char *app, *arg = NULL; + app = switch_core_session_strdup(tech_pvt->session, var); + + if (strstr(app, "::")) { + switch_core_session_execute_application_async(tech_pvt->session, app, arg); + } else { + if ((arg = strchr(app, ' '))) { + *arg++ = '\0'; + } + + switch_core_session_execute_application(tech_pvt->session, app, arg); + } + } + return t38_options; } @@ -5166,7 +5231,7 @@ static int recover_callback(void *pArg, int argc, char **argv, char **columnName tech_pvt->local_sdp_str = switch_core_session_strdup(session, tmp); } - if ((tmp = switch_channel_get_variable(channel, "switch_r_sdp"))) { + if ((tmp = switch_channel_get_variable(channel, SWITCH_R_SDP_VARIABLE))) { tech_pvt->remote_sdp_str = switch_core_session_strdup(session, tmp); } diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c index 89eb1ae948..91808a7f50 100644 --- a/src/mod/endpoints/mod_sofia/sofia_presence.c +++ b/src/mod/endpoints/mod_sofia/sofia_presence.c @@ -91,6 +91,7 @@ switch_status_t sofia_presence_chat_send(const char *proto, const char *from, co char *user_via = NULL; char *contact_str = NULL; char *dup_dest = NULL; + char *p = NULL; char *remote_host = NULL; if (!to) { @@ -187,7 +188,12 @@ switch_status_t sofia_presence_chat_send(const char *proto, const char *from, co /* sofia_glue is running sofia_overcome_sip_uri_weakness we do not, not sure if it matters */ - dup_dest = strdup(dst->contact); + if (dst->route_uri) { + dup_dest = strdup(dst->route_uri); + } else { + dup_dest = strdup(dst->to); + } + if (dst->route_uri) { remote_host = strdup(dst->route_uri); @@ -226,17 +232,12 @@ switch_status_t sofia_presence_chat_send(const char *proto, const char *from, co contact_str = profile->url; } - switch_safe_free(dup_dest); - switch_safe_free(remote_host); - status = SWITCH_STATUS_SUCCESS; - /* - if ((p = strstr(contact, ";fs_"))) { + if (dup_dest && (p = strstr(dup_dest, ";fs_"))) { *p = '\0'; } - */ - + /* if this cries, add contact here too, change the 1 to 0 and omit the safe_free */ msg_nh = nua_handle(profile->nua, NULL, @@ -244,7 +245,7 @@ switch_status_t sofia_presence_chat_send(const char *proto, const char *from, co TAG_IF(dst->route, SIPTAG_ROUTE_STR(dst->route)), SIPTAG_FROM_STR(from), TAG_IF(contact, NUTAG_URL(contact)), - SIPTAG_TO_STR(dst->to), + SIPTAG_TO_STR(dup_dest), SIPTAG_CONTACT_STR(contact_str), TAG_END()); @@ -257,6 +258,8 @@ switch_status_t sofia_presence_chat_send(const char *proto, const char *from, co TAG_END()); sofia_glue_free_destination(dst); + switch_safe_free(dup_dest); + switch_safe_free(remote_host); } switch_console_free_matches(&list); diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c index 5109e0bc72..6e3649a68f 100644 --- a/src/mod/endpoints/mod_sofia/sofia_reg.c +++ b/src/mod/endpoints/mod_sofia/sofia_reg.c @@ -653,7 +653,7 @@ void sofia_reg_check_expire(sofia_profile_t *profile, time_t now, int reboot) "and profile_name='%s' and expires <= %ld", mod_sofia_globals.hostname, profile->name, (long) now); sofia_glue_execute_sql_callback(profile, NULL, sql, sofia_sla_dialog_del_callback, profile); - switch_snprintf(sql, sizeof(sql), "delete from sip_registrations where expires > 0 and hostname='%s' and expires <= %ld", + switch_snprintf(sql, sizeof(sql), "delete from sip_shared_appearance_dialogs where expires > 0 and hostname='%s' and expires <= %ld", mod_sofia_globals.hostname, (long) now); diff --git a/src/mod/event_handlers/mod_snmp/Makefile b/src/mod/event_handlers/mod_snmp/Makefile index 1d8827daf1..f95227b4b5 100644 --- a/src/mod/event_handlers/mod_snmp/Makefile +++ b/src/mod/event_handlers/mod_snmp/Makefile @@ -1,6 +1,6 @@ include ../../../../build/modmake.rules -LOCAL_CFLAGS=-I `net-snmp-config --cflags` +LOCAL_CFLAGS=`net-snmp-config --cflags` LOCAL_LDFLAGS=`net-snmp-config --agent-libs` LOCAL_OBJS=subagent.o diff --git a/src/mod/event_handlers/mod_snmp/subagent.c b/src/mod/event_handlers/mod_snmp/subagent.c index 43975ee4e0..871fb5ad75 100644 --- a/src/mod/event_handlers/mod_snmp/subagent.c +++ b/src/mod/event_handlers/mod_snmp/subagent.c @@ -67,42 +67,42 @@ static int channelList_callback(void *pArg, int argc, char **argv, char **column netsnmp_tdata_row *row; switch_zmalloc(entry, sizeof(chan_entry_t)); - if (!entry) - return 0; row = netsnmp_tdata_create_row(); + if (!row) { switch_safe_free(entry); return 0; } + row->data = entry; entry->idx = idx++; - strncpy(entry->uuid, argv[0], sizeof(entry->uuid)); - strncpy(entry->direction, argv[1], sizeof(entry->direction)); + strncpy(entry->uuid, switch_str_nil(argv[0]), sizeof(entry->uuid)); + strncpy(entry->direction, switch_str_nil(argv[1]), sizeof(entry->direction)); entry->created_epoch = atoi(argv[3]); - strncpy(entry->name, argv[4], sizeof(entry->name)); - strncpy(entry->state, argv[5], sizeof(entry->state)); - strncpy(entry->cid_name, argv[6], sizeof(entry->cid_name)); - strncpy(entry->cid_num, argv[7], sizeof(entry->cid_num)); - strncpy(entry->dest, argv[9], sizeof(entry->dest)); - strncpy(entry->application, argv[10], sizeof(entry->application)); - strncpy(entry->application_data, argv[11], sizeof(entry->application_data)); - strncpy(entry->dialplan, argv[12], sizeof(entry->dialplan)); - strncpy(entry->context, argv[13], sizeof(entry->context)); - strncpy(entry->read_codec, argv[14], sizeof(entry->read_codec)); - entry->read_rate = atoi(argv[15]); - entry->read_bitrate = atoi(argv[16]); - strncpy(entry->write_codec, argv[17], sizeof(entry->write_codec)); - entry->write_rate = atoi(argv[18]); - entry->write_bitrate = atoi(argv[19]); + strncpy(entry->name, switch_str_nil(argv[4]), sizeof(entry->name)); + strncpy(entry->state, switch_str_nil(argv[5]), sizeof(entry->state)); + strncpy(entry->cid_name, switch_str_nil(argv[6]), sizeof(entry->cid_name)); + strncpy(entry->cid_num, switch_str_nil(argv[7]), sizeof(entry->cid_num)); + strncpy(entry->dest, switch_str_nil(argv[9]), sizeof(entry->dest)); + strncpy(entry->application, switch_str_nil(argv[10]), sizeof(entry->application)); + strncpy(entry->application_data, switch_str_nil(argv[11]), sizeof(entry->application_data)); + strncpy(entry->dialplan, switch_str_nil(argv[12]), sizeof(entry->dialplan)); + strncpy(entry->context, switch_str_nil(argv[13]), sizeof(entry->context)); + strncpy(entry->read_codec, switch_str_nil(argv[14]), sizeof(entry->read_codec)); + entry->read_rate = atoi(switch_str_nil(argv[15])); + entry->read_bitrate = atoi(switch_str_nil(argv[16])); + strncpy(entry->write_codec, switch_str_nil(argv[17]), sizeof(entry->write_codec)); + entry->write_rate = atoi(switch_str_nil(argv[18])); + entry->write_bitrate = atoi(switch_str_nil(argv[19])); memset(&entry->ip_addr, 0, sizeof(entry->ip_addr)); - if (strchr(argv[8], ':')) { - switch_inet_pton(AF_INET6, argv[8], &entry->ip_addr); + if (strchr(switch_str_nil(argv[8]), ':')) { + switch_inet_pton(AF_INET6, switch_str_nil(argv[8]), &entry->ip_addr); entry->addr_family = AF_INET6; } else { - switch_inet_pton(AF_INET, argv[8], &entry->ip_addr); + switch_inet_pton(AF_INET, switch_str_nil(argv[8]), &entry->ip_addr); entry->addr_family = AF_INET; } @@ -128,7 +128,7 @@ void channelList_free(netsnmp_cache *cache, void *magic) int channelList_load(netsnmp_cache *cache, void *vmagic) { switch_cache_db_handle_t *dbh; - char sql[1024] = "", hostname[256] = ""; + char sql[1024] = ""; channelList_free(cache, NULL); @@ -137,8 +137,8 @@ int channelList_load(netsnmp_cache *cache, void *vmagic) } idx = 1; - gethostname(hostname, sizeof(hostname)); - sprintf(sql, "SELECT * FROM channels WHERE hostname='%s' ORDER BY created_epoch", hostname); + + sprintf(sql, "SELECT * FROM channels WHERE hostname='%s' ORDER BY created_epoch", switch_core_get_hostname()); switch_cache_db_execute_sql_callback(dbh, sql, channelList_callback, NULL, NULL); switch_cache_db_release_db_handle(&dbh); @@ -282,6 +282,9 @@ int handle_channelList(netsnmp_mib_handler *handler, netsnmp_handler_registratio switch (reqinfo->mode) { case MODE_GET: for (request = requests; request; request = request->next) { + if (request->processed) + continue; + table_info = netsnmp_extract_table_info(request); entry = (chan_entry_t *) netsnmp_tdata_extract_entry(request); @@ -366,7 +369,7 @@ int handle_channelList(netsnmp_mib_handler *handler, netsnmp_handler_registratio break; default: /* we should never get here, so this is a really bad error */ - snmp_log(LOG_ERR, "Unknown mode (%d) in handle_foo\n", reqinfo->mode ); + snmp_log(LOG_ERR, "Unknown mode (%d) in handle_channelList\n", reqinfo->mode ); return SNMP_ERR_GENERR; } diff --git a/src/mod/formats/mod_shout/Makefile b/src/mod/formats/mod_shout/Makefile index 0ff6fc6525..7388bc0c67 100644 --- a/src/mod/formats/mod_shout/Makefile +++ b/src/mod/formats/mod_shout/Makefile @@ -1,6 +1,6 @@ LAME=lame-3.97 SHOUT=libshout-2.2.2 -MPG123=mpg123 +MPG123=mpg123-1.13.2 BASE=../../../.. WANT_CURL=yes diff --git a/src/mod/languages/mod_java/src/org/freeswitch/swig/freeswitch.java b/src/mod/languages/mod_java/src/org/freeswitch/swig/freeswitch.java index 7b53db475c..ea825c9014 100644 --- a/src/mod/languages/mod_java/src/org/freeswitch/swig/freeswitch.java +++ b/src/mod/languages/mod_java/src/org/freeswitch/swig/freeswitch.java @@ -17,6 +17,10 @@ public class freeswitch { freeswitchJNI.consoleCleanLog(msg); } + public static boolean email(String to, String from, String headers, String body, String file, String convert_cmd, String convert_ext) { + return freeswitchJNI.email(to, from, headers, body, file, convert_cmd, convert_ext); + } + public static void console_log(String level_str, String msg) { freeswitchJNI.console_log(level_str, msg); } diff --git a/src/mod/languages/mod_java/src/org/freeswitch/swig/freeswitchJNI.java b/src/mod/languages/mod_java/src/org/freeswitch/swig/freeswitchJNI.java index f90a9cca11..5e778de59c 100644 --- a/src/mod/languages/mod_java/src/org/freeswitch/swig/freeswitchJNI.java +++ b/src/mod/languages/mod_java/src/org/freeswitch/swig/freeswitchJNI.java @@ -11,6 +11,7 @@ package org.freeswitch.swig; class freeswitchJNI { public final static native void consoleLog(String jarg1, String jarg2); public final static native void consoleCleanLog(String jarg1); + public final static native boolean email(String jarg1, String jarg2, String jarg3, String jarg4, String jarg5, String jarg6, String jarg7); public final static native long new_IVRMenu(long jarg1, IVRMenu jarg1_, String jarg2, String jarg3, String jarg4, String jarg5, String jarg6, String jarg7, String jarg8, String jarg9, String jarg10, int jarg11, int jarg12, int jarg13, int jarg14, int jarg15, int jarg16); public final static native void delete_IVRMenu(long jarg1); public final static native void IVRMenu_bindAction(long jarg1, IVRMenu jarg1_, String jarg2, String jarg3, String jarg4); diff --git a/src/mod/languages/mod_java/switch_swig_wrap.cpp b/src/mod/languages/mod_java/switch_swig_wrap.cpp index 720e7571db..34f62d5c9d 100644 --- a/src/mod/languages/mod_java/switch_swig_wrap.cpp +++ b/src/mod/languages/mod_java/switch_swig_wrap.cpp @@ -244,6 +244,67 @@ SWIGEXPORT void JNICALL Java_org_freeswitch_swig_freeswitchJNI_consoleCleanLog(J } +SWIGEXPORT jboolean JNICALL Java_org_freeswitch_swig_freeswitchJNI_email(JNIEnv *jenv, jclass jcls, jstring jarg1, jstring jarg2, jstring jarg3, jstring jarg4, jstring jarg5, jstring jarg6, jstring jarg7) { + jboolean jresult = 0 ; + char *arg1 = (char *) 0 ; + char *arg2 = (char *) 0 ; + char *arg3 = (char *) NULL ; + char *arg4 = (char *) NULL ; + char *arg5 = (char *) NULL ; + char *arg6 = (char *) NULL ; + char *arg7 = (char *) NULL ; + bool result; + + (void)jenv; + (void)jcls; + arg1 = 0; + if (jarg1) { + arg1 = (char *)jenv->GetStringUTFChars(jarg1, 0); + if (!arg1) return 0; + } + arg2 = 0; + if (jarg2) { + arg2 = (char *)jenv->GetStringUTFChars(jarg2, 0); + if (!arg2) return 0; + } + arg3 = 0; + if (jarg3) { + arg3 = (char *)jenv->GetStringUTFChars(jarg3, 0); + if (!arg3) return 0; + } + arg4 = 0; + if (jarg4) { + arg4 = (char *)jenv->GetStringUTFChars(jarg4, 0); + if (!arg4) return 0; + } + arg5 = 0; + if (jarg5) { + arg5 = (char *)jenv->GetStringUTFChars(jarg5, 0); + if (!arg5) return 0; + } + arg6 = 0; + if (jarg6) { + arg6 = (char *)jenv->GetStringUTFChars(jarg6, 0); + if (!arg6) return 0; + } + arg7 = 0; + if (jarg7) { + arg7 = (char *)jenv->GetStringUTFChars(jarg7, 0); + if (!arg7) return 0; + } + result = (bool)email(arg1,arg2,arg3,arg4,arg5,arg6,arg7); + jresult = (jboolean)result; + if (arg1) jenv->ReleaseStringUTFChars(jarg1, (const char *)arg1); + if (arg2) jenv->ReleaseStringUTFChars(jarg2, (const char *)arg2); + if (arg3) jenv->ReleaseStringUTFChars(jarg3, (const char *)arg3); + if (arg4) jenv->ReleaseStringUTFChars(jarg4, (const char *)arg4); + if (arg5) jenv->ReleaseStringUTFChars(jarg5, (const char *)arg5); + if (arg6) jenv->ReleaseStringUTFChars(jarg6, (const char *)arg6); + if (arg7) jenv->ReleaseStringUTFChars(jarg7, (const char *)arg7); + return jresult; +} + + SWIGEXPORT jlong JNICALL Java_org_freeswitch_swig_freeswitchJNI_new_1IVRMenu(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jstring jarg2, jstring jarg3, jstring jarg4, jstring jarg5, jstring jarg6, jstring jarg7, jstring jarg8, jstring jarg9, jstring jarg10, jint jarg11, jint jarg12, jint jarg13, jint jarg14, jint jarg15, jint jarg16) { jlong jresult = 0 ; IVRMenu *arg1 = (IVRMenu *) 0 ; diff --git a/src/mod/languages/mod_managed/freeswitch_wrap.2010.cxx b/src/mod/languages/mod_managed/freeswitch_wrap.2010.cxx index 808d548bdf..fdf2c5f08d 100644 --- a/src/mod/languages/mod_managed/freeswitch_wrap.2010.cxx +++ b/src/mod/languages/mod_managed/freeswitch_wrap.2010.cxx @@ -7182,6 +7182,42 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_switch_core_get_variable(char * jarg1) { } +SWIGEXPORT char * SWIGSTDCALL CSharp_switch_core_get_variable_dup(char * jarg1) { + char * jresult ; + char *arg1 = (char *) 0 ; + char *result = 0 ; + + arg1 = (char *)jarg1; + result = (char *)switch_core_get_variable_dup((char const *)arg1); + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + +SWIGEXPORT char * SWIGSTDCALL CSharp_switch_core_get_variable_pdup(char * jarg1, void * jarg2) { + char * jresult ; + char *arg1 = (char *) 0 ; + switch_memory_pool_t *arg2 = (switch_memory_pool_t *) 0 ; + char *result = 0 ; + + arg1 = (char *)jarg1; + arg2 = (switch_memory_pool_t *)jarg2; + result = (char *)switch_core_get_variable_pdup((char const *)arg1,arg2); + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + +SWIGEXPORT char * SWIGSTDCALL CSharp_switch_core_get_hostname() { + char * jresult ; + char *result = 0 ; + + result = (char *)switch_core_get_hostname(); + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + SWIGEXPORT void SWIGSTDCALL CSharp_switch_core_set_variable(char * jarg1, char * jarg2) { char *arg1 = (char *) 0 ; char *arg2 = (char *) 0 ; @@ -10071,293 +10107,6 @@ SWIGEXPORT void SWIGSTDCALL CSharp_delete_switch_cache_db_connection_options_t(v } -SWIGEXPORT void SWIGSTDCALL CSharp_switch_cache_db_handle_t_name_set(void * jarg1, char * jarg2) { - switch_cache_db_handle_t *arg1 = (switch_cache_db_handle_t *) 0 ; - char *arg2 ; - - arg1 = (switch_cache_db_handle_t *)jarg1; - arg2 = (char *)jarg2; - { - if(arg2) { - strncpy((char*)arg1->name, (const char *)arg2, 256-1); - arg1->name[256-1] = 0; - } else { - arg1->name[0] = 0; - } - } -} - - -SWIGEXPORT char * SWIGSTDCALL CSharp_switch_cache_db_handle_t_name_get(void * jarg1) { - char * jresult ; - switch_cache_db_handle_t *arg1 = (switch_cache_db_handle_t *) 0 ; - char *result = 0 ; - - arg1 = (switch_cache_db_handle_t *)jarg1; - result = (char *)(char *) ((arg1)->name); - jresult = SWIG_csharp_string_callback((const char *)result); - return jresult; -} - - -SWIGEXPORT void SWIGSTDCALL CSharp_switch_cache_db_handle_t_type_set(void * jarg1, int jarg2) { - switch_cache_db_handle_t *arg1 = (switch_cache_db_handle_t *) 0 ; - switch_cache_db_handle_type_t arg2 ; - - arg1 = (switch_cache_db_handle_t *)jarg1; - arg2 = (switch_cache_db_handle_type_t)jarg2; - if (arg1) (arg1)->type = arg2; -} - - -SWIGEXPORT int SWIGSTDCALL CSharp_switch_cache_db_handle_t_type_get(void * jarg1) { - int jresult ; - switch_cache_db_handle_t *arg1 = (switch_cache_db_handle_t *) 0 ; - switch_cache_db_handle_type_t result; - - arg1 = (switch_cache_db_handle_t *)jarg1; - result = (switch_cache_db_handle_type_t) ((arg1)->type); - jresult = result; - return jresult; -} - - -SWIGEXPORT void SWIGSTDCALL CSharp_switch_cache_db_handle_t_native_handle_set(void * jarg1, void * jarg2) { - switch_cache_db_handle_t *arg1 = (switch_cache_db_handle_t *) 0 ; - switch_cache_db_native_handle_t *arg2 = (switch_cache_db_native_handle_t *) 0 ; - - arg1 = (switch_cache_db_handle_t *)jarg1; - arg2 = (switch_cache_db_native_handle_t *)jarg2; - if (arg1) (arg1)->native_handle = *arg2; -} - - -SWIGEXPORT void * SWIGSTDCALL CSharp_switch_cache_db_handle_t_native_handle_get(void * jarg1) { - void * jresult ; - switch_cache_db_handle_t *arg1 = (switch_cache_db_handle_t *) 0 ; - switch_cache_db_native_handle_t *result = 0 ; - - arg1 = (switch_cache_db_handle_t *)jarg1; - result = (switch_cache_db_native_handle_t *)& ((arg1)->native_handle); - jresult = (void *)result; - return jresult; -} - - -SWIGEXPORT void SWIGSTDCALL CSharp_switch_cache_db_handle_t_last_used_set(void * jarg1, void * jarg2) { - switch_cache_db_handle_t *arg1 = (switch_cache_db_handle_t *) 0 ; - time_t arg2 ; - time_t *argp2 ; - - arg1 = (switch_cache_db_handle_t *)jarg1; - argp2 = (time_t *)jarg2; - if (!argp2) { - SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, "Attempt to dereference null time_t", 0); - return ; - } - arg2 = *argp2; - if (arg1) (arg1)->last_used = arg2; -} - - -SWIGEXPORT void * SWIGSTDCALL CSharp_switch_cache_db_handle_t_last_used_get(void * jarg1) { - void * jresult ; - switch_cache_db_handle_t *arg1 = (switch_cache_db_handle_t *) 0 ; - time_t result; - - arg1 = (switch_cache_db_handle_t *)jarg1; - result = ((arg1)->last_used); - jresult = new time_t((const time_t &)result); - return jresult; -} - - -SWIGEXPORT void SWIGSTDCALL CSharp_switch_cache_db_handle_t_mutex_set(void * jarg1, void * jarg2) { - switch_cache_db_handle_t *arg1 = (switch_cache_db_handle_t *) 0 ; - switch_mutex_t *arg2 = (switch_mutex_t *) 0 ; - - arg1 = (switch_cache_db_handle_t *)jarg1; - arg2 = (switch_mutex_t *)jarg2; - if (arg1) (arg1)->mutex = arg2; -} - - -SWIGEXPORT void * SWIGSTDCALL CSharp_switch_cache_db_handle_t_mutex_get(void * jarg1) { - void * jresult ; - switch_cache_db_handle_t *arg1 = (switch_cache_db_handle_t *) 0 ; - switch_mutex_t *result = 0 ; - - arg1 = (switch_cache_db_handle_t *)jarg1; - result = (switch_mutex_t *) ((arg1)->mutex); - jresult = (void *)result; - return jresult; -} - - -SWIGEXPORT void SWIGSTDCALL CSharp_switch_cache_db_handle_t_io_mutex_set(void * jarg1, void * jarg2) { - switch_cache_db_handle_t *arg1 = (switch_cache_db_handle_t *) 0 ; - switch_mutex_t *arg2 = (switch_mutex_t *) 0 ; - - arg1 = (switch_cache_db_handle_t *)jarg1; - arg2 = (switch_mutex_t *)jarg2; - if (arg1) (arg1)->io_mutex = arg2; -} - - -SWIGEXPORT void * SWIGSTDCALL CSharp_switch_cache_db_handle_t_io_mutex_get(void * jarg1) { - void * jresult ; - switch_cache_db_handle_t *arg1 = (switch_cache_db_handle_t *) 0 ; - switch_mutex_t *result = 0 ; - - arg1 = (switch_cache_db_handle_t *)jarg1; - result = (switch_mutex_t *) ((arg1)->io_mutex); - jresult = (void *)result; - return jresult; -} - - -SWIGEXPORT void SWIGSTDCALL CSharp_switch_cache_db_handle_t_pool_set(void * jarg1, void * jarg2) { - switch_cache_db_handle_t *arg1 = (switch_cache_db_handle_t *) 0 ; - switch_memory_pool_t *arg2 = (switch_memory_pool_t *) 0 ; - - arg1 = (switch_cache_db_handle_t *)jarg1; - arg2 = (switch_memory_pool_t *)jarg2; - if (arg1) (arg1)->pool = arg2; -} - - -SWIGEXPORT void * SWIGSTDCALL CSharp_switch_cache_db_handle_t_pool_get(void * jarg1) { - void * jresult ; - switch_cache_db_handle_t *arg1 = (switch_cache_db_handle_t *) 0 ; - switch_memory_pool_t *result = 0 ; - - arg1 = (switch_cache_db_handle_t *)jarg1; - result = (switch_memory_pool_t *) ((arg1)->pool); - jresult = (void *)result; - return jresult; -} - - -SWIGEXPORT void SWIGSTDCALL CSharp_switch_cache_db_handle_t_flags_set(void * jarg1, int jarg2) { - switch_cache_db_handle_t *arg1 = (switch_cache_db_handle_t *) 0 ; - int32_t arg2 ; - - arg1 = (switch_cache_db_handle_t *)jarg1; - arg2 = (int32_t)jarg2; - if (arg1) (arg1)->flags = arg2; -} - - -SWIGEXPORT int SWIGSTDCALL CSharp_switch_cache_db_handle_t_flags_get(void * jarg1) { - int jresult ; - switch_cache_db_handle_t *arg1 = (switch_cache_db_handle_t *) 0 ; - int32_t result; - - arg1 = (switch_cache_db_handle_t *)jarg1; - result = (int32_t) ((arg1)->flags); - jresult = result; - return jresult; -} - - -SWIGEXPORT void SWIGSTDCALL CSharp_switch_cache_db_handle_t_hash_set(void * jarg1, unsigned long jarg2) { - switch_cache_db_handle_t *arg1 = (switch_cache_db_handle_t *) 0 ; - unsigned long arg2 ; - - arg1 = (switch_cache_db_handle_t *)jarg1; - arg2 = (unsigned long)jarg2; - if (arg1) (arg1)->hash = arg2; -} - - -SWIGEXPORT unsigned long SWIGSTDCALL CSharp_switch_cache_db_handle_t_hash_get(void * jarg1) { - unsigned long jresult ; - switch_cache_db_handle_t *arg1 = (switch_cache_db_handle_t *) 0 ; - unsigned long result; - - arg1 = (switch_cache_db_handle_t *)jarg1; - result = (unsigned long) ((arg1)->hash); - jresult = (unsigned long)result; - return jresult; -} - - -SWIGEXPORT void SWIGSTDCALL CSharp_switch_cache_db_handle_t_creator_set(void * jarg1, char * jarg2) { - switch_cache_db_handle_t *arg1 = (switch_cache_db_handle_t *) 0 ; - char *arg2 ; - - arg1 = (switch_cache_db_handle_t *)jarg1; - arg2 = (char *)jarg2; - { - if(arg2) { - strncpy((char*)arg1->creator, (const char *)arg2, 256-1); - arg1->creator[256-1] = 0; - } else { - arg1->creator[0] = 0; - } - } -} - - -SWIGEXPORT char * SWIGSTDCALL CSharp_switch_cache_db_handle_t_creator_get(void * jarg1) { - char * jresult ; - switch_cache_db_handle_t *arg1 = (switch_cache_db_handle_t *) 0 ; - char *result = 0 ; - - arg1 = (switch_cache_db_handle_t *)jarg1; - result = (char *)(char *) ((arg1)->creator); - jresult = SWIG_csharp_string_callback((const char *)result); - return jresult; -} - - -SWIGEXPORT void SWIGSTDCALL CSharp_switch_cache_db_handle_t_last_user_set(void * jarg1, char * jarg2) { - switch_cache_db_handle_t *arg1 = (switch_cache_db_handle_t *) 0 ; - char *arg2 ; - - arg1 = (switch_cache_db_handle_t *)jarg1; - arg2 = (char *)jarg2; - { - if(arg2) { - strncpy((char*)arg1->last_user, (const char *)arg2, 256-1); - arg1->last_user[256-1] = 0; - } else { - arg1->last_user[0] = 0; - } - } -} - - -SWIGEXPORT char * SWIGSTDCALL CSharp_switch_cache_db_handle_t_last_user_get(void * jarg1) { - char * jresult ; - switch_cache_db_handle_t *arg1 = (switch_cache_db_handle_t *) 0 ; - char *result = 0 ; - - arg1 = (switch_cache_db_handle_t *)jarg1; - result = (char *)(char *) ((arg1)->last_user); - jresult = SWIG_csharp_string_callback((const char *)result); - return jresult; -} - - -SWIGEXPORT void * SWIGSTDCALL CSharp_new_switch_cache_db_handle_t() { - void * jresult ; - switch_cache_db_handle_t *result = 0 ; - - result = (switch_cache_db_handle_t *)new switch_cache_db_handle_t(); - jresult = (void *)result; - return jresult; -} - - -SWIGEXPORT void SWIGSTDCALL CSharp_delete_switch_cache_db_handle_t(void * jarg1) { - switch_cache_db_handle_t *arg1 = (switch_cache_db_handle_t *) 0 ; - - arg1 = (switch_cache_db_handle_t *)jarg1; - delete arg1; -} - - SWIGEXPORT char * SWIGSTDCALL CSharp_switch_cache_db_type_name(int jarg1) { char * jresult ; switch_cache_db_handle_type_t arg1 ; @@ -10370,6 +10119,18 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_switch_cache_db_type_name(int jarg1) { } +SWIGEXPORT int SWIGSTDCALL CSharp_switch_cache_db_get_type(void * jarg1) { + int jresult ; + switch_cache_db_handle_t *arg1 = (switch_cache_db_handle_t *) 0 ; + switch_cache_db_handle_type_t result; + + arg1 = (switch_cache_db_handle_t *)jarg1; + result = (switch_cache_db_handle_type_t)switch_cache_db_get_type(arg1); + jresult = result; + return jresult; +} + + SWIGEXPORT void SWIGSTDCALL CSharp_switch_cache_db_dismiss_db_handle(void * jarg1) { switch_cache_db_handle_t **arg1 = (switch_cache_db_handle_t **) 0 ; @@ -10386,14 +10147,6 @@ SWIGEXPORT void SWIGSTDCALL CSharp_switch_cache_db_release_db_handle(void * jarg } -SWIGEXPORT void SWIGSTDCALL CSharp_switch_cache_db_destroy_db_handle(void * jarg1) { - switch_cache_db_handle_t **arg1 = (switch_cache_db_handle_t **) 0 ; - - arg1 = (switch_cache_db_handle_t **)jarg1; - switch_cache_db_destroy_db_handle(arg1); -} - - SWIGEXPORT int SWIGSTDCALL CSharp__switch_cache_db_get_db_handle(void * jarg1, int jarg2, void * jarg3, char * jarg4, char * jarg5, int jarg6) { int jresult ; switch_cache_db_handle_t **arg1 = (switch_cache_db_handle_t **) 0 ; @@ -10560,11 +10313,6 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_cache_db_persistant_execute_trans(void } -SWIGEXPORT void SWIGSTDCALL CSharp_switch_cache_db_detach() { - switch_cache_db_detach(); -} - - SWIGEXPORT unsigned long SWIGSTDCALL CSharp_switch_core_debug_level() { unsigned long jresult ; uint32_t result; @@ -10616,6 +10364,60 @@ SWIGEXPORT unsigned long SWIGSTDCALL CSharp_switch_default_ptime(char * jarg1, u } +SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_add_registration(char * jarg1, char * jarg2, char * jarg3, char * jarg4, unsigned long jarg5, char * jarg6, char * jarg7, char * jarg8) { + int jresult ; + char *arg1 = (char *) 0 ; + char *arg2 = (char *) 0 ; + char *arg3 = (char *) 0 ; + char *arg4 = (char *) 0 ; + uint32_t arg5 ; + char *arg6 = (char *) 0 ; + char *arg7 = (char *) 0 ; + char *arg8 = (char *) 0 ; + switch_status_t result; + + arg1 = (char *)jarg1; + arg2 = (char *)jarg2; + arg3 = (char *)jarg3; + arg4 = (char *)jarg4; + arg5 = (uint32_t)jarg5; + arg6 = (char *)jarg6; + arg7 = (char *)jarg7; + arg8 = (char *)jarg8; + result = (switch_status_t)switch_core_add_registration((char const *)arg1,(char const *)arg2,(char const *)arg3,(char const *)arg4,arg5,(char const *)arg6,(char const *)arg7,(char const *)arg8); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_del_registration(char * jarg1, char * jarg2, char * jarg3) { + int jresult ; + char *arg1 = (char *) 0 ; + char *arg2 = (char *) 0 ; + char *arg3 = (char *) 0 ; + switch_status_t result; + + arg1 = (char *)jarg1; + arg2 = (char *)jarg2; + arg3 = (char *)jarg3; + result = (switch_status_t)switch_core_del_registration((char const *)arg1,(char const *)arg2,(char const *)arg3); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_expire_registration(int jarg1) { + int jresult ; + int arg1 ; + switch_status_t result; + + arg1 = (int)jarg1; + result = (switch_status_t)switch_core_expire_registration(arg1); + jresult = result; + return jresult; +} + + SWIGEXPORT void SWIGSTDCALL CSharp_switch_loadable_module_interface_module_name_set(void * jarg1, char * jarg2) { switch_loadable_module_interface *arg1 = (switch_loadable_module_interface *) 0 ; char *arg2 = (char *) 0 ; @@ -25728,6 +25530,18 @@ SWIGEXPORT void SWIGSTDCALL CSharp_switch_change_sln_volume(void * jarg1, unsign } +SWIGEXPORT void SWIGSTDCALL CSharp_switch_change_sln_volume_granular(void * jarg1, unsigned long jarg2, int jarg3) { + int16_t *arg1 = (int16_t *) 0 ; + uint32_t arg2 ; + int32_t arg3 ; + + arg1 = (int16_t *)jarg1; + arg2 = (uint32_t)jarg2; + arg3 = (int32_t)jarg3; + switch_change_sln_volume_granular(arg1,arg2,arg3); +} + + SWIGEXPORT unsigned long SWIGSTDCALL CSharp_switch_merge_sln(void * jarg1, unsigned long jarg2, void * jarg3, unsigned long jarg4) { unsigned long jresult ; int16_t *arg1 = (int16_t *) 0 ; @@ -28723,13 +28537,14 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_rtp_activate_rtcp(void * jarg1, int jar } -SWIGEXPORT int SWIGSTDCALL CSharp_switch_rtp_activate_jitter_buffer(void * jarg1, unsigned long jarg2, unsigned long jarg3, unsigned long jarg4, unsigned long jarg5) { +SWIGEXPORT int SWIGSTDCALL CSharp_switch_rtp_activate_jitter_buffer(void * jarg1, unsigned long jarg2, unsigned long jarg3, unsigned long jarg4, unsigned long jarg5, unsigned long jarg6) { int jresult ; switch_rtp_t *arg1 = (switch_rtp_t *) 0 ; uint32_t arg2 ; uint32_t arg3 ; uint32_t arg4 ; uint32_t arg5 ; + uint32_t arg6 ; switch_status_t result; arg1 = (switch_rtp_t *)jarg1; @@ -28737,7 +28552,8 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_rtp_activate_jitter_buffer(void * jarg1 arg3 = (uint32_t)jarg3; arg4 = (uint32_t)jarg4; arg5 = (uint32_t)jarg5; - result = (switch_status_t)switch_rtp_activate_jitter_buffer(arg1,arg2,arg3,arg4,arg5); + arg6 = (uint32_t)jarg6; + result = (switch_status_t)switch_rtp_activate_jitter_buffer(arg1,arg2,arg3,arg4,arg5,arg6); jresult = result; return jresult; } @@ -29121,6 +28937,16 @@ SWIGEXPORT void SWIGSTDCALL CSharp_switch_rtp_set_telephony_recv_event(void * ja } +SWIGEXPORT void SWIGSTDCALL CSharp_switch_rtp_set_recv_pt(void * jarg1, unsigned char jarg2) { + switch_rtp_t *arg1 = (switch_rtp_t *) 0 ; + switch_payload_t arg2 ; + + arg1 = (switch_rtp_t *)jarg1; + arg2 = (switch_payload_t)jarg2; + switch_rtp_set_recv_pt(arg1,arg2); +} + + SWIGEXPORT void SWIGSTDCALL CSharp_switch_rtp_set_cng_pt(void * jarg1, unsigned char jarg2) { switch_rtp_t *arg1 = (switch_rtp_t *) 0 ; switch_payload_t arg2 ; @@ -32587,6 +32413,30 @@ SWIGEXPORT void SWIGSTDCALL CSharp_consoleCleanLog(char * jarg1) { } +SWIGEXPORT unsigned int SWIGSTDCALL CSharp_email(char * jarg1, char * jarg2, char * jarg3, char * jarg4, char * jarg5, char * jarg6, char * jarg7) { + unsigned int jresult ; + char *arg1 = (char *) 0 ; + char *arg2 = (char *) 0 ; + char *arg3 = (char *) NULL ; + char *arg4 = (char *) NULL ; + char *arg5 = (char *) NULL ; + char *arg6 = (char *) NULL ; + char *arg7 = (char *) NULL ; + bool result; + + arg1 = (char *)jarg1; + arg2 = (char *)jarg2; + arg3 = (char *)jarg3; + arg4 = (char *)jarg4; + arg5 = (char *)jarg5; + arg6 = (char *)jarg6; + arg7 = (char *)jarg7; + result = (bool)email(arg1,arg2,arg3,arg4,arg5,arg6,arg7); + jresult = result; + return jresult; +} + + SWIGEXPORT void * SWIGSTDCALL CSharp_new_IvrMenu(void * jarg1, char * jarg2, char * jarg3, char * jarg4, char * jarg5, char * jarg6, char * jarg7, char * jarg8, char * jarg9, char * jarg10, int jarg11, int jarg12, int jarg13, int jarg14, int jarg15, int jarg16) { void * jresult ; IVRMenu *arg1 = (IVRMenu *) 0 ; diff --git a/src/mod/languages/mod_managed/freeswitch_wrap.cxx b/src/mod/languages/mod_managed/freeswitch_wrap.cxx index 71e9f99819..72dd0cb45e 100644 --- a/src/mod/languages/mod_managed/freeswitch_wrap.cxx +++ b/src/mod/languages/mod_managed/freeswitch_wrap.cxx @@ -7473,6 +7473,42 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_switch_core_get_variable(char * jarg1) { } +SWIGEXPORT char * SWIGSTDCALL CSharp_switch_core_get_variable_dup(char * jarg1) { + char * jresult ; + char *arg1 = (char *) 0 ; + char *result = 0 ; + + arg1 = (char *)jarg1; + result = (char *)switch_core_get_variable_dup((char const *)arg1); + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + +SWIGEXPORT char * SWIGSTDCALL CSharp_switch_core_get_variable_pdup(char * jarg1, void * jarg2) { + char * jresult ; + char *arg1 = (char *) 0 ; + switch_memory_pool_t *arg2 = (switch_memory_pool_t *) 0 ; + char *result = 0 ; + + arg1 = (char *)jarg1; + arg2 = (switch_memory_pool_t *)jarg2; + result = (char *)switch_core_get_variable_pdup((char const *)arg1,arg2); + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + +SWIGEXPORT char * SWIGSTDCALL CSharp_switch_core_get_hostname() { + char * jresult ; + char *result = 0 ; + + result = (char *)switch_core_get_hostname(); + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + SWIGEXPORT void SWIGSTDCALL CSharp_switch_core_set_variable(char * jarg1, char * jarg2) { char *arg1 = (char *) 0 ; char *arg2 = (char *) 0 ; @@ -10371,290 +10407,6 @@ SWIGEXPORT void SWIGSTDCALL CSharp_delete_switch_cache_db_connection_options_t(v } -SWIGEXPORT void SWIGSTDCALL CSharp_switch_cache_db_handle_t_name_set(void * jarg1, char * jarg2) { - switch_cache_db_handle_t *arg1 = (switch_cache_db_handle_t *) 0 ; - char *arg2 ; - - arg1 = (switch_cache_db_handle_t *)jarg1; - arg2 = (char *)jarg2; - { - if (arg2) strncpy((char *)arg1->name, (const char *)arg2, 256); - else arg1->name[0] = 0; - } -} - - -SWIGEXPORT char * SWIGSTDCALL CSharp_switch_cache_db_handle_t_name_get(void * jarg1) { - char * jresult ; - switch_cache_db_handle_t *arg1 = (switch_cache_db_handle_t *) 0 ; - char *result = 0 ; - - arg1 = (switch_cache_db_handle_t *)jarg1; - result = (char *)(char *) ((arg1)->name); - jresult = SWIG_csharp_string_callback((const char *)result); - return jresult; -} - - -SWIGEXPORT void SWIGSTDCALL CSharp_switch_cache_db_handle_t_type_set(void * jarg1, int jarg2) { - switch_cache_db_handle_t *arg1 = (switch_cache_db_handle_t *) 0 ; - switch_cache_db_handle_type_t arg2 ; - - arg1 = (switch_cache_db_handle_t *)jarg1; - arg2 = (switch_cache_db_handle_type_t)jarg2; - if (arg1) (arg1)->type = arg2; - -} - - -SWIGEXPORT int SWIGSTDCALL CSharp_switch_cache_db_handle_t_type_get(void * jarg1) { - int jresult ; - switch_cache_db_handle_t *arg1 = (switch_cache_db_handle_t *) 0 ; - switch_cache_db_handle_type_t result; - - arg1 = (switch_cache_db_handle_t *)jarg1; - result = (switch_cache_db_handle_type_t) ((arg1)->type); - jresult = result; - return jresult; -} - - -SWIGEXPORT void SWIGSTDCALL CSharp_switch_cache_db_handle_t_native_handle_set(void * jarg1, void * jarg2) { - switch_cache_db_handle_t *arg1 = (switch_cache_db_handle_t *) 0 ; - switch_cache_db_native_handle_t *arg2 = (switch_cache_db_native_handle_t *) 0 ; - - arg1 = (switch_cache_db_handle_t *)jarg1; - arg2 = (switch_cache_db_native_handle_t *)jarg2; - if (arg1) (arg1)->native_handle = *arg2; - -} - - -SWIGEXPORT void * SWIGSTDCALL CSharp_switch_cache_db_handle_t_native_handle_get(void * jarg1) { - void * jresult ; - switch_cache_db_handle_t *arg1 = (switch_cache_db_handle_t *) 0 ; - switch_cache_db_native_handle_t *result = 0 ; - - arg1 = (switch_cache_db_handle_t *)jarg1; - result = (switch_cache_db_native_handle_t *)& ((arg1)->native_handle); - jresult = (void *)result; - return jresult; -} - - -SWIGEXPORT void SWIGSTDCALL CSharp_switch_cache_db_handle_t_last_used_set(void * jarg1, void * jarg2) { - switch_cache_db_handle_t *arg1 = (switch_cache_db_handle_t *) 0 ; - time_t arg2 ; - time_t *argp2 ; - - arg1 = (switch_cache_db_handle_t *)jarg1; - argp2 = (time_t *)jarg2; - if (!argp2) { - SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, "Attempt to dereference null time_t", 0); - return ; - } - arg2 = *argp2; - if (arg1) (arg1)->last_used = arg2; - -} - - -SWIGEXPORT void * SWIGSTDCALL CSharp_switch_cache_db_handle_t_last_used_get(void * jarg1) { - void * jresult ; - switch_cache_db_handle_t *arg1 = (switch_cache_db_handle_t *) 0 ; - time_t result; - - arg1 = (switch_cache_db_handle_t *)jarg1; - result = ((arg1)->last_used); - jresult = new time_t((time_t &)result); - return jresult; -} - - -SWIGEXPORT void SWIGSTDCALL CSharp_switch_cache_db_handle_t_mutex_set(void * jarg1, void * jarg2) { - switch_cache_db_handle_t *arg1 = (switch_cache_db_handle_t *) 0 ; - switch_mutex_t *arg2 = (switch_mutex_t *) 0 ; - - arg1 = (switch_cache_db_handle_t *)jarg1; - arg2 = (switch_mutex_t *)jarg2; - if (arg1) (arg1)->mutex = arg2; - -} - - -SWIGEXPORT void * SWIGSTDCALL CSharp_switch_cache_db_handle_t_mutex_get(void * jarg1) { - void * jresult ; - switch_cache_db_handle_t *arg1 = (switch_cache_db_handle_t *) 0 ; - switch_mutex_t *result = 0 ; - - arg1 = (switch_cache_db_handle_t *)jarg1; - result = (switch_mutex_t *) ((arg1)->mutex); - jresult = (void *)result; - return jresult; -} - - -SWIGEXPORT void SWIGSTDCALL CSharp_switch_cache_db_handle_t_io_mutex_set(void * jarg1, void * jarg2) { - switch_cache_db_handle_t *arg1 = (switch_cache_db_handle_t *) 0 ; - switch_mutex_t *arg2 = (switch_mutex_t *) 0 ; - - arg1 = (switch_cache_db_handle_t *)jarg1; - arg2 = (switch_mutex_t *)jarg2; - if (arg1) (arg1)->io_mutex = arg2; - -} - - -SWIGEXPORT void * SWIGSTDCALL CSharp_switch_cache_db_handle_t_io_mutex_get(void * jarg1) { - void * jresult ; - switch_cache_db_handle_t *arg1 = (switch_cache_db_handle_t *) 0 ; - switch_mutex_t *result = 0 ; - - arg1 = (switch_cache_db_handle_t *)jarg1; - result = (switch_mutex_t *) ((arg1)->io_mutex); - jresult = (void *)result; - return jresult; -} - - -SWIGEXPORT void SWIGSTDCALL CSharp_switch_cache_db_handle_t_pool_set(void * jarg1, void * jarg2) { - switch_cache_db_handle_t *arg1 = (switch_cache_db_handle_t *) 0 ; - switch_memory_pool_t *arg2 = (switch_memory_pool_t *) 0 ; - - arg1 = (switch_cache_db_handle_t *)jarg1; - arg2 = (switch_memory_pool_t *)jarg2; - if (arg1) (arg1)->pool = arg2; - -} - - -SWIGEXPORT void * SWIGSTDCALL CSharp_switch_cache_db_handle_t_pool_get(void * jarg1) { - void * jresult ; - switch_cache_db_handle_t *arg1 = (switch_cache_db_handle_t *) 0 ; - switch_memory_pool_t *result = 0 ; - - arg1 = (switch_cache_db_handle_t *)jarg1; - result = (switch_memory_pool_t *) ((arg1)->pool); - jresult = (void *)result; - return jresult; -} - - -SWIGEXPORT void SWIGSTDCALL CSharp_switch_cache_db_handle_t_flags_set(void * jarg1, int jarg2) { - switch_cache_db_handle_t *arg1 = (switch_cache_db_handle_t *) 0 ; - int32_t arg2 ; - - arg1 = (switch_cache_db_handle_t *)jarg1; - arg2 = (int32_t)jarg2; - if (arg1) (arg1)->flags = arg2; - -} - - -SWIGEXPORT int SWIGSTDCALL CSharp_switch_cache_db_handle_t_flags_get(void * jarg1) { - int jresult ; - switch_cache_db_handle_t *arg1 = (switch_cache_db_handle_t *) 0 ; - int32_t result; - - arg1 = (switch_cache_db_handle_t *)jarg1; - result = (int32_t) ((arg1)->flags); - jresult = result; - return jresult; -} - - -SWIGEXPORT void SWIGSTDCALL CSharp_switch_cache_db_handle_t_hash_set(void * jarg1, unsigned long jarg2) { - switch_cache_db_handle_t *arg1 = (switch_cache_db_handle_t *) 0 ; - unsigned long arg2 ; - - arg1 = (switch_cache_db_handle_t *)jarg1; - arg2 = (unsigned long)jarg2; - if (arg1) (arg1)->hash = arg2; - -} - - -SWIGEXPORT unsigned long SWIGSTDCALL CSharp_switch_cache_db_handle_t_hash_get(void * jarg1) { - unsigned long jresult ; - switch_cache_db_handle_t *arg1 = (switch_cache_db_handle_t *) 0 ; - unsigned long result; - - arg1 = (switch_cache_db_handle_t *)jarg1; - result = (unsigned long) ((arg1)->hash); - jresult = (unsigned long)result; - return jresult; -} - - -SWIGEXPORT void SWIGSTDCALL CSharp_switch_cache_db_handle_t_creator_set(void * jarg1, char * jarg2) { - switch_cache_db_handle_t *arg1 = (switch_cache_db_handle_t *) 0 ; - char *arg2 ; - - arg1 = (switch_cache_db_handle_t *)jarg1; - arg2 = (char *)jarg2; - { - if (arg2) strncpy((char *)arg1->creator, (const char *)arg2, 256); - else arg1->creator[0] = 0; - } -} - - -SWIGEXPORT char * SWIGSTDCALL CSharp_switch_cache_db_handle_t_creator_get(void * jarg1) { - char * jresult ; - switch_cache_db_handle_t *arg1 = (switch_cache_db_handle_t *) 0 ; - char *result = 0 ; - - arg1 = (switch_cache_db_handle_t *)jarg1; - result = (char *)(char *) ((arg1)->creator); - jresult = SWIG_csharp_string_callback((const char *)result); - return jresult; -} - - -SWIGEXPORT void SWIGSTDCALL CSharp_switch_cache_db_handle_t_last_user_set(void * jarg1, char * jarg2) { - switch_cache_db_handle_t *arg1 = (switch_cache_db_handle_t *) 0 ; - char *arg2 ; - - arg1 = (switch_cache_db_handle_t *)jarg1; - arg2 = (char *)jarg2; - { - if (arg2) strncpy((char *)arg1->last_user, (const char *)arg2, 256); - else arg1->last_user[0] = 0; - } -} - - -SWIGEXPORT char * SWIGSTDCALL CSharp_switch_cache_db_handle_t_last_user_get(void * jarg1) { - char * jresult ; - switch_cache_db_handle_t *arg1 = (switch_cache_db_handle_t *) 0 ; - char *result = 0 ; - - arg1 = (switch_cache_db_handle_t *)jarg1; - result = (char *)(char *) ((arg1)->last_user); - jresult = SWIG_csharp_string_callback((const char *)result); - return jresult; -} - - -SWIGEXPORT void * SWIGSTDCALL CSharp_new_switch_cache_db_handle_t() { - void * jresult ; - switch_cache_db_handle_t *result = 0 ; - - result = (switch_cache_db_handle_t *)new switch_cache_db_handle_t(); - jresult = (void *)result; - return jresult; -} - - -SWIGEXPORT void SWIGSTDCALL CSharp_delete_switch_cache_db_handle_t(void * jarg1) { - switch_cache_db_handle_t *arg1 = (switch_cache_db_handle_t *) 0 ; - - arg1 = (switch_cache_db_handle_t *)jarg1; - delete arg1; - -} - - SWIGEXPORT char * SWIGSTDCALL CSharp_switch_cache_db_type_name(int jarg1) { char * jresult ; switch_cache_db_handle_type_t arg1 ; @@ -10667,6 +10419,18 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_switch_cache_db_type_name(int jarg1) { } +SWIGEXPORT int SWIGSTDCALL CSharp_switch_cache_db_get_type(void * jarg1) { + int jresult ; + switch_cache_db_handle_t *arg1 = (switch_cache_db_handle_t *) 0 ; + switch_cache_db_handle_type_t result; + + arg1 = (switch_cache_db_handle_t *)jarg1; + result = (switch_cache_db_handle_type_t)switch_cache_db_get_type(arg1); + jresult = result; + return jresult; +} + + SWIGEXPORT void SWIGSTDCALL CSharp_switch_cache_db_dismiss_db_handle(void * jarg1) { switch_cache_db_handle_t **arg1 = (switch_cache_db_handle_t **) 0 ; @@ -10683,14 +10447,6 @@ SWIGEXPORT void SWIGSTDCALL CSharp_switch_cache_db_release_db_handle(void * jarg } -SWIGEXPORT void SWIGSTDCALL CSharp_switch_cache_db_destroy_db_handle(void * jarg1) { - switch_cache_db_handle_t **arg1 = (switch_cache_db_handle_t **) 0 ; - - arg1 = (switch_cache_db_handle_t **)jarg1; - switch_cache_db_destroy_db_handle(arg1); -} - - SWIGEXPORT int SWIGSTDCALL CSharp__switch_cache_db_get_db_handle(void * jarg1, int jarg2, void * jarg3, char * jarg4, char * jarg5, int jarg6) { int jresult ; switch_cache_db_handle_t **arg1 = (switch_cache_db_handle_t **) 0 ; @@ -10857,11 +10613,6 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_cache_db_persistant_execute_trans(void } -SWIGEXPORT void SWIGSTDCALL CSharp_switch_cache_db_detach() { - switch_cache_db_detach(); -} - - SWIGEXPORT unsigned long SWIGSTDCALL CSharp_switch_core_debug_level() { unsigned long jresult ; uint32_t result; @@ -10913,6 +10664,60 @@ SWIGEXPORT unsigned long SWIGSTDCALL CSharp_switch_default_ptime(char * jarg1, u } +SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_add_registration(char * jarg1, char * jarg2, char * jarg3, char * jarg4, unsigned long jarg5, char * jarg6, char * jarg7, char * jarg8) { + int jresult ; + char *arg1 = (char *) 0 ; + char *arg2 = (char *) 0 ; + char *arg3 = (char *) 0 ; + char *arg4 = (char *) 0 ; + uint32_t arg5 ; + char *arg6 = (char *) 0 ; + char *arg7 = (char *) 0 ; + char *arg8 = (char *) 0 ; + switch_status_t result; + + arg1 = (char *)jarg1; + arg2 = (char *)jarg2; + arg3 = (char *)jarg3; + arg4 = (char *)jarg4; + arg5 = (uint32_t)jarg5; + arg6 = (char *)jarg6; + arg7 = (char *)jarg7; + arg8 = (char *)jarg8; + result = (switch_status_t)switch_core_add_registration((char const *)arg1,(char const *)arg2,(char const *)arg3,(char const *)arg4,arg5,(char const *)arg6,(char const *)arg7,(char const *)arg8); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_del_registration(char * jarg1, char * jarg2, char * jarg3) { + int jresult ; + char *arg1 = (char *) 0 ; + char *arg2 = (char *) 0 ; + char *arg3 = (char *) 0 ; + switch_status_t result; + + arg1 = (char *)jarg1; + arg2 = (char *)jarg2; + arg3 = (char *)jarg3; + result = (switch_status_t)switch_core_del_registration((char const *)arg1,(char const *)arg2,(char const *)arg3); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_expire_registration(int jarg1) { + int jresult ; + int arg1 ; + switch_status_t result; + + arg1 = (int)jarg1; + result = (switch_status_t)switch_core_expire_registration(arg1); + jresult = result; + return jresult; +} + + SWIGEXPORT void SWIGSTDCALL CSharp_switch_loadable_module_interface_module_name_set(void * jarg1, char * jarg2) { switch_loadable_module_interface *arg1 = (switch_loadable_module_interface *) 0 ; char *arg2 = (char *) 0 ; @@ -26411,6 +26216,18 @@ SWIGEXPORT void SWIGSTDCALL CSharp_switch_change_sln_volume(void * jarg1, unsign } +SWIGEXPORT void SWIGSTDCALL CSharp_switch_change_sln_volume_granular(void * jarg1, unsigned long jarg2, int jarg3) { + int16_t *arg1 = (int16_t *) 0 ; + uint32_t arg2 ; + int32_t arg3 ; + + arg1 = (int16_t *)jarg1; + arg2 = (uint32_t)jarg2; + arg3 = (int32_t)jarg3; + switch_change_sln_volume_granular(arg1,arg2,arg3); +} + + SWIGEXPORT unsigned long SWIGSTDCALL CSharp_switch_merge_sln(void * jarg1, unsigned long jarg2, void * jarg3, unsigned long jarg4) { unsigned long jresult ; int16_t *arg1 = (int16_t *) 0 ; @@ -29431,13 +29248,14 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_rtp_activate_rtcp(void * jarg1, int jar } -SWIGEXPORT int SWIGSTDCALL CSharp_switch_rtp_activate_jitter_buffer(void * jarg1, unsigned long jarg2, unsigned long jarg3, unsigned long jarg4, unsigned long jarg5) { +SWIGEXPORT int SWIGSTDCALL CSharp_switch_rtp_activate_jitter_buffer(void * jarg1, unsigned long jarg2, unsigned long jarg3, unsigned long jarg4, unsigned long jarg5, unsigned long jarg6) { int jresult ; switch_rtp_t *arg1 = (switch_rtp_t *) 0 ; uint32_t arg2 ; uint32_t arg3 ; uint32_t arg4 ; uint32_t arg5 ; + uint32_t arg6 ; switch_status_t result; arg1 = (switch_rtp_t *)jarg1; @@ -29445,7 +29263,8 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_rtp_activate_jitter_buffer(void * jarg1 arg3 = (uint32_t)jarg3; arg4 = (uint32_t)jarg4; arg5 = (uint32_t)jarg5; - result = (switch_status_t)switch_rtp_activate_jitter_buffer(arg1,arg2,arg3,arg4,arg5); + arg6 = (uint32_t)jarg6; + result = (switch_status_t)switch_rtp_activate_jitter_buffer(arg1,arg2,arg3,arg4,arg5,arg6); jresult = result; return jresult; } @@ -29829,6 +29648,16 @@ SWIGEXPORT void SWIGSTDCALL CSharp_switch_rtp_set_telephony_recv_event(void * ja } +SWIGEXPORT void SWIGSTDCALL CSharp_switch_rtp_set_recv_pt(void * jarg1, unsigned char jarg2) { + switch_rtp_t *arg1 = (switch_rtp_t *) 0 ; + switch_payload_t arg2 ; + + arg1 = (switch_rtp_t *)jarg1; + arg2 = (switch_payload_t)jarg2; + switch_rtp_set_recv_pt(arg1,arg2); +} + + SWIGEXPORT void SWIGSTDCALL CSharp_switch_rtp_set_cng_pt(void * jarg1, unsigned char jarg2) { switch_rtp_t *arg1 = (switch_rtp_t *) 0 ; switch_payload_t arg2 ; diff --git a/src/mod/languages/mod_managed/managed/swig.2010.cs b/src/mod/languages/mod_managed/managed/swig.2010.cs index 61c0a4e462..eb6d93531c 100644 --- a/src/mod/languages/mod_managed/managed/swig.2010.cs +++ b/src/mod/languages/mod_managed/managed/swig.2010.cs @@ -1394,6 +1394,21 @@ public class freeswitch { return ret; } + public static string switch_core_get_variable_dup(string varname) { + string ret = freeswitchPINVOKE.switch_core_get_variable_dup(varname); + return ret; + } + + public static string switch_core_get_variable_pdup(string varname, SWIGTYPE_p_apr_pool_t pool) { + string ret = freeswitchPINVOKE.switch_core_get_variable_pdup(varname, SWIGTYPE_p_apr_pool_t.getCPtr(pool)); + return ret; + } + + public static string switch_core_get_hostname() { + string ret = freeswitchPINVOKE.switch_core_get_hostname(); + return ret; + } + public static void switch_core_set_variable(string varname, string value) { freeswitchPINVOKE.switch_core_set_variable(varname, value); } @@ -2336,40 +2351,41 @@ public class freeswitch { return ret; } - public static void switch_cache_db_dismiss_db_handle(SWIGTYPE_p_p_switch_cache_db_handle_t dbh) { - freeswitchPINVOKE.switch_cache_db_dismiss_db_handle(SWIGTYPE_p_p_switch_cache_db_handle_t.getCPtr(dbh)); - } - - public static void switch_cache_db_release_db_handle(SWIGTYPE_p_p_switch_cache_db_handle_t dbh) { - freeswitchPINVOKE.switch_cache_db_release_db_handle(SWIGTYPE_p_p_switch_cache_db_handle_t.getCPtr(dbh)); - } - - public static void switch_cache_db_destroy_db_handle(SWIGTYPE_p_p_switch_cache_db_handle_t dbh) { - freeswitchPINVOKE.switch_cache_db_destroy_db_handle(SWIGTYPE_p_p_switch_cache_db_handle_t.getCPtr(dbh)); - } - - public static switch_status_t _switch_cache_db_get_db_handle(SWIGTYPE_p_p_switch_cache_db_handle_t dbh, switch_cache_db_handle_type_t type, switch_cache_db_connection_options_t connection_options, string file, string func, int line) { - switch_status_t ret = (switch_status_t)freeswitchPINVOKE._switch_cache_db_get_db_handle(SWIGTYPE_p_p_switch_cache_db_handle_t.getCPtr(dbh), (int)type, switch_cache_db_connection_options_t.getCPtr(connection_options), file, func, line); + public static switch_cache_db_handle_type_t switch_cache_db_get_type(SWIGTYPE_p_switch_cache_db_handle dbh) { + switch_cache_db_handle_type_t ret = (switch_cache_db_handle_type_t)freeswitchPINVOKE.switch_cache_db_get_type(SWIGTYPE_p_switch_cache_db_handle.getCPtr(dbh)); return ret; } - public static string switch_cache_db_execute_sql2str(switch_cache_db_handle_t dbh, string sql, string str, uint len, ref string err) { - string ret = freeswitchPINVOKE.switch_cache_db_execute_sql2str(switch_cache_db_handle_t.getCPtr(dbh), sql, str, len, ref err); + public static void switch_cache_db_dismiss_db_handle(SWIGTYPE_p_p_switch_cache_db_handle dbh) { + freeswitchPINVOKE.switch_cache_db_dismiss_db_handle(SWIGTYPE_p_p_switch_cache_db_handle.getCPtr(dbh)); + } + + public static void switch_cache_db_release_db_handle(SWIGTYPE_p_p_switch_cache_db_handle dbh) { + freeswitchPINVOKE.switch_cache_db_release_db_handle(SWIGTYPE_p_p_switch_cache_db_handle.getCPtr(dbh)); + } + + public static switch_status_t _switch_cache_db_get_db_handle(SWIGTYPE_p_p_switch_cache_db_handle dbh, switch_cache_db_handle_type_t type, switch_cache_db_connection_options_t connection_options, string file, string func, int line) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE._switch_cache_db_get_db_handle(SWIGTYPE_p_p_switch_cache_db_handle.getCPtr(dbh), (int)type, switch_cache_db_connection_options_t.getCPtr(connection_options), file, func, line); return ret; } - public static switch_status_t switch_cache_db_execute_sql(switch_cache_db_handle_t dbh, string sql, ref string err) { - switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_cache_db_execute_sql(switch_cache_db_handle_t.getCPtr(dbh), sql, ref err); + public static string switch_cache_db_execute_sql2str(SWIGTYPE_p_switch_cache_db_handle dbh, string sql, string str, uint len, ref string err) { + string ret = freeswitchPINVOKE.switch_cache_db_execute_sql2str(SWIGTYPE_p_switch_cache_db_handle.getCPtr(dbh), sql, str, len, ref err); return ret; } - public static switch_status_t switch_cache_db_execute_sql_callback(switch_cache_db_handle_t dbh, string sql, SWIGTYPE_p_f_p_void_int_p_p_char_p_p_char__int callback, SWIGTYPE_p_void pdata, ref string err) { - switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_cache_db_execute_sql_callback(switch_cache_db_handle_t.getCPtr(dbh), sql, SWIGTYPE_p_f_p_void_int_p_p_char_p_p_char__int.getCPtr(callback), SWIGTYPE_p_void.getCPtr(pdata), ref err); + public static switch_status_t switch_cache_db_execute_sql(SWIGTYPE_p_switch_cache_db_handle dbh, string sql, ref string err) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_cache_db_execute_sql(SWIGTYPE_p_switch_cache_db_handle.getCPtr(dbh), sql, ref err); return ret; } - public static int switch_cache_db_affected_rows(switch_cache_db_handle_t dbh) { - int ret = freeswitchPINVOKE.switch_cache_db_affected_rows(switch_cache_db_handle_t.getCPtr(dbh)); + public static switch_status_t switch_cache_db_execute_sql_callback(SWIGTYPE_p_switch_cache_db_handle dbh, string sql, SWIGTYPE_p_f_p_void_int_p_p_char_p_p_char__int callback, SWIGTYPE_p_void pdata, ref string err) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_cache_db_execute_sql_callback(SWIGTYPE_p_switch_cache_db_handle.getCPtr(dbh), sql, SWIGTYPE_p_f_p_void_int_p_p_char_p_p_char__int.getCPtr(callback), SWIGTYPE_p_void.getCPtr(pdata), ref err); + return ret; + } + + public static int switch_cache_db_affected_rows(SWIGTYPE_p_switch_cache_db_handle dbh) { + int ret = freeswitchPINVOKE.switch_cache_db_affected_rows(SWIGTYPE_p_switch_cache_db_handle.getCPtr(dbh)); return ret; } @@ -2377,30 +2393,26 @@ public class freeswitch { freeswitchPINVOKE.switch_cache_db_status(switch_stream_handle.getCPtr(stream)); } - public static switch_status_t _switch_core_db_handle(SWIGTYPE_p_p_switch_cache_db_handle_t dbh, string file, string func, int line) { - switch_status_t ret = (switch_status_t)freeswitchPINVOKE._switch_core_db_handle(SWIGTYPE_p_p_switch_cache_db_handle_t.getCPtr(dbh), file, func, line); + public static switch_status_t _switch_core_db_handle(SWIGTYPE_p_p_switch_cache_db_handle dbh, string file, string func, int line) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE._switch_core_db_handle(SWIGTYPE_p_p_switch_cache_db_handle.getCPtr(dbh), file, func, line); return ret; } - public static switch_bool_t switch_cache_db_test_reactive(switch_cache_db_handle_t db, string test_sql, string drop_sql, string reactive_sql) { - switch_bool_t ret = (switch_bool_t)freeswitchPINVOKE.switch_cache_db_test_reactive(switch_cache_db_handle_t.getCPtr(db), test_sql, drop_sql, reactive_sql); + public static switch_bool_t switch_cache_db_test_reactive(SWIGTYPE_p_switch_cache_db_handle db, string test_sql, string drop_sql, string reactive_sql) { + switch_bool_t ret = (switch_bool_t)freeswitchPINVOKE.switch_cache_db_test_reactive(SWIGTYPE_p_switch_cache_db_handle.getCPtr(db), test_sql, drop_sql, reactive_sql); return ret; } - public static switch_status_t switch_cache_db_persistant_execute(switch_cache_db_handle_t dbh, string sql, uint retries) { - switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_cache_db_persistant_execute(switch_cache_db_handle_t.getCPtr(dbh), sql, retries); + public static switch_status_t switch_cache_db_persistant_execute(SWIGTYPE_p_switch_cache_db_handle dbh, string sql, uint retries) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_cache_db_persistant_execute(SWIGTYPE_p_switch_cache_db_handle.getCPtr(dbh), sql, retries); return ret; } - public static switch_status_t switch_cache_db_persistant_execute_trans(switch_cache_db_handle_t dbh, string sql, uint retries) { - switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_cache_db_persistant_execute_trans(switch_cache_db_handle_t.getCPtr(dbh), sql, retries); + public static switch_status_t switch_cache_db_persistant_execute_trans(SWIGTYPE_p_switch_cache_db_handle dbh, string sql, uint retries) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_cache_db_persistant_execute_trans(SWIGTYPE_p_switch_cache_db_handle.getCPtr(dbh), sql, retries); return ret; } - public static void switch_cache_db_detach() { - freeswitchPINVOKE.switch_cache_db_detach(); - } - public static uint switch_core_debug_level() { uint ret = freeswitchPINVOKE.switch_core_debug_level(); return ret; @@ -2425,6 +2437,21 @@ public class freeswitch { return ret; } + public static switch_status_t switch_core_add_registration(string user, string realm, string token, string url, uint expires, string network_ip, string network_port, string network_proto) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_core_add_registration(user, realm, token, url, expires, network_ip, network_port, network_proto); + return ret; + } + + public static switch_status_t switch_core_del_registration(string user, string realm, string token) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_core_del_registration(user, realm, token); + return ret; + } + + public static switch_status_t switch_core_expire_registration(int force) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_core_expire_registration(force); + return ret; + } + public static switch_status_t switch_loadable_module_init(switch_bool_t autoload) { switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_loadable_module_init((int)autoload); return ret; @@ -3984,6 +4011,10 @@ public class freeswitch { freeswitchPINVOKE.switch_change_sln_volume(SWIGTYPE_p_short.getCPtr(data), samples, vol); } + public static void switch_change_sln_volume_granular(SWIGTYPE_p_short data, uint samples, int vol) { + freeswitchPINVOKE.switch_change_sln_volume_granular(SWIGTYPE_p_short.getCPtr(data), samples, vol); + } + public static uint switch_merge_sln(SWIGTYPE_p_short data, uint samples, SWIGTYPE_p_short other_data, uint other_samples) { uint ret = freeswitchPINVOKE.switch_merge_sln(SWIGTYPE_p_short.getCPtr(data), samples, SWIGTYPE_p_short.getCPtr(other_data), other_samples); return ret; @@ -4729,8 +4760,8 @@ public class freeswitch { return ret; } - public static switch_status_t switch_rtp_activate_jitter_buffer(SWIGTYPE_p_switch_rtp rtp_session, uint queue_frames, uint max_queue_frames, uint samples_per_packet, uint samples_per_second) { - switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_rtp_activate_jitter_buffer(SWIGTYPE_p_switch_rtp.getCPtr(rtp_session), queue_frames, max_queue_frames, samples_per_packet, samples_per_second); + public static switch_status_t switch_rtp_activate_jitter_buffer(SWIGTYPE_p_switch_rtp rtp_session, uint queue_frames, uint max_queue_frames, uint samples_per_packet, uint samples_per_second, uint max_drift) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_rtp_activate_jitter_buffer(SWIGTYPE_p_switch_rtp.getCPtr(rtp_session), queue_frames, max_queue_frames, samples_per_packet, samples_per_second, max_drift); return ret; } @@ -4867,6 +4898,10 @@ public class freeswitch { freeswitchPINVOKE.switch_rtp_set_telephony_recv_event(SWIGTYPE_p_switch_rtp.getCPtr(rtp_session), te); } + public static void switch_rtp_set_recv_pt(SWIGTYPE_p_switch_rtp rtp_session, byte pt) { + freeswitchPINVOKE.switch_rtp_set_recv_pt(SWIGTYPE_p_switch_rtp.getCPtr(rtp_session), pt); + } + public static void switch_rtp_set_cng_pt(SWIGTYPE_p_switch_rtp rtp_session, byte pt) { freeswitchPINVOKE.switch_rtp_set_cng_pt(SWIGTYPE_p_switch_rtp.getCPtr(rtp_session), pt); } @@ -5374,6 +5409,11 @@ public class freeswitch { freeswitchPINVOKE.consoleCleanLog(msg); } + public static bool email(string to, string from, string headers, string body, string file, string convert_cmd, string convert_ext) { + bool ret = freeswitchPINVOKE.email(to, from, headers, body, file, convert_cmd, convert_ext); + return ret; + } + public static void console_log(string level_str, string msg) { freeswitchPINVOKE.console_log(level_str, msg); } @@ -7578,6 +7618,15 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_core_get_variable")] public static extern string switch_core_get_variable(string jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_get_variable_dup")] + public static extern string switch_core_get_variable_dup(string jarg1); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_get_variable_pdup")] + public static extern string switch_core_get_variable_pdup(string jarg1, HandleRef jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_get_hostname")] + public static extern string switch_core_get_hostname(); + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_set_variable")] public static extern void switch_core_set_variable(string jarg1, string jarg2); @@ -8226,90 +8275,18 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_delete_switch_cache_db_connection_options_t")] public static extern void delete_switch_cache_db_connection_options_t(HandleRef jarg1); - [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_handle_t_name_set")] - public static extern void switch_cache_db_handle_t_name_set(HandleRef jarg1, string jarg2); - - [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_handle_t_name_get")] - public static extern string switch_cache_db_handle_t_name_get(HandleRef jarg1); - - [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_handle_t_type_set")] - public static extern void switch_cache_db_handle_t_type_set(HandleRef jarg1, int jarg2); - - [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_handle_t_type_get")] - public static extern int switch_cache_db_handle_t_type_get(HandleRef jarg1); - - [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_handle_t_native_handle_set")] - public static extern void switch_cache_db_handle_t_native_handle_set(HandleRef jarg1, HandleRef jarg2); - - [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_handle_t_native_handle_get")] - public static extern IntPtr switch_cache_db_handle_t_native_handle_get(HandleRef jarg1); - - [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_handle_t_last_used_set")] - public static extern void switch_cache_db_handle_t_last_used_set(HandleRef jarg1, HandleRef jarg2); - - [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_handle_t_last_used_get")] - public static extern IntPtr switch_cache_db_handle_t_last_used_get(HandleRef jarg1); - - [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_handle_t_mutex_set")] - public static extern void switch_cache_db_handle_t_mutex_set(HandleRef jarg1, HandleRef jarg2); - - [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_handle_t_mutex_get")] - public static extern IntPtr switch_cache_db_handle_t_mutex_get(HandleRef jarg1); - - [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_handle_t_io_mutex_set")] - public static extern void switch_cache_db_handle_t_io_mutex_set(HandleRef jarg1, HandleRef jarg2); - - [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_handle_t_io_mutex_get")] - public static extern IntPtr switch_cache_db_handle_t_io_mutex_get(HandleRef jarg1); - - [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_handle_t_pool_set")] - public static extern void switch_cache_db_handle_t_pool_set(HandleRef jarg1, HandleRef jarg2); - - [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_handle_t_pool_get")] - public static extern IntPtr switch_cache_db_handle_t_pool_get(HandleRef jarg1); - - [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_handle_t_flags_set")] - public static extern void switch_cache_db_handle_t_flags_set(HandleRef jarg1, int jarg2); - - [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_handle_t_flags_get")] - public static extern int switch_cache_db_handle_t_flags_get(HandleRef jarg1); - - [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_handle_t_hash_set")] - public static extern void switch_cache_db_handle_t_hash_set(HandleRef jarg1, uint jarg2); - - [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_handle_t_hash_get")] - public static extern uint switch_cache_db_handle_t_hash_get(HandleRef jarg1); - - [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_handle_t_creator_set")] - public static extern void switch_cache_db_handle_t_creator_set(HandleRef jarg1, string jarg2); - - [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_handle_t_creator_get")] - public static extern string switch_cache_db_handle_t_creator_get(HandleRef jarg1); - - [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_handle_t_last_user_set")] - public static extern void switch_cache_db_handle_t_last_user_set(HandleRef jarg1, string jarg2); - - [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_handle_t_last_user_get")] - public static extern string switch_cache_db_handle_t_last_user_get(HandleRef jarg1); - - [DllImport("mod_managed", EntryPoint="CSharp_new_switch_cache_db_handle_t")] - public static extern IntPtr new_switch_cache_db_handle_t(); - - [DllImport("mod_managed", EntryPoint="CSharp_delete_switch_cache_db_handle_t")] - public static extern void delete_switch_cache_db_handle_t(HandleRef jarg1); - [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_type_name")] public static extern string switch_cache_db_type_name(int jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_get_type")] + public static extern int switch_cache_db_get_type(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_dismiss_db_handle")] public static extern void switch_cache_db_dismiss_db_handle(HandleRef jarg1); [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_release_db_handle")] public static extern void switch_cache_db_release_db_handle(HandleRef jarg1); - [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_destroy_db_handle")] - public static extern void switch_cache_db_destroy_db_handle(HandleRef jarg1); - [DllImport("mod_managed", EntryPoint="CSharp__switch_cache_db_get_db_handle")] public static extern int _switch_cache_db_get_db_handle(HandleRef jarg1, int jarg2, HandleRef jarg3, string jarg4, string jarg5, int jarg6); @@ -8340,9 +8317,6 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_persistant_execute_trans")] public static extern int switch_cache_db_persistant_execute_trans(HandleRef jarg1, string jarg2, uint jarg3); - [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_detach")] - public static extern void switch_cache_db_detach(); - [DllImport("mod_managed", EntryPoint="CSharp_switch_core_debug_level")] public static extern uint switch_core_debug_level(); @@ -8358,6 +8332,15 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_default_ptime")] public static extern uint switch_default_ptime(string jarg1, uint jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_add_registration")] + public static extern int switch_core_add_registration(string jarg1, string jarg2, string jarg3, string jarg4, uint jarg5, string jarg6, string jarg7, string jarg8); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_del_registration")] + public static extern int switch_core_del_registration(string jarg1, string jarg2, string jarg3); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_expire_registration")] + public static extern int switch_core_expire_registration(int jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_loadable_module_interface_module_name_set")] public static extern void switch_loadable_module_interface_module_name_set(HandleRef jarg1, string jarg2); @@ -12051,6 +12034,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_change_sln_volume")] public static extern void switch_change_sln_volume(HandleRef jarg1, uint jarg2, int jarg3); + [DllImport("mod_managed", EntryPoint="CSharp_switch_change_sln_volume_granular")] + public static extern void switch_change_sln_volume_granular(HandleRef jarg1, uint jarg2, int jarg3); + [DllImport("mod_managed", EntryPoint="CSharp_switch_merge_sln")] public static extern uint switch_merge_sln(HandleRef jarg1, uint jarg2, HandleRef jarg3, uint jarg4); @@ -12661,7 +12647,7 @@ class freeswitchPINVOKE { public static extern int switch_rtp_activate_rtcp(HandleRef jarg1, int jarg2, ushort jarg3); [DllImport("mod_managed", EntryPoint="CSharp_switch_rtp_activate_jitter_buffer")] - public static extern int switch_rtp_activate_jitter_buffer(HandleRef jarg1, uint jarg2, uint jarg3, uint jarg4, uint jarg5); + public static extern int switch_rtp_activate_jitter_buffer(HandleRef jarg1, uint jarg2, uint jarg3, uint jarg4, uint jarg5, uint jarg6); [DllImport("mod_managed", EntryPoint="CSharp_switch_rtp_debug_jitter_buffer")] public static extern int switch_rtp_debug_jitter_buffer(HandleRef jarg1, string jarg2); @@ -12747,6 +12733,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_rtp_set_telephony_recv_event")] public static extern void switch_rtp_set_telephony_recv_event(HandleRef jarg1, byte jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_rtp_set_recv_pt")] + public static extern void switch_rtp_set_recv_pt(HandleRef jarg1, byte jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_rtp_set_cng_pt")] public static extern void switch_rtp_set_cng_pt(HandleRef jarg1, byte jarg2); @@ -13602,6 +13591,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_consoleCleanLog")] public static extern void consoleCleanLog(string jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_email")] + public static extern bool email(string jarg1, string jarg2, string jarg3, string jarg4, string jarg5, string jarg6, string jarg7); + [DllImport("mod_managed", EntryPoint="CSharp_new_IvrMenu")] public static extern IntPtr new_IvrMenu(HandleRef jarg1, string jarg2, string jarg3, string jarg4, string jarg5, string jarg6, string jarg7, string jarg8, string jarg9, string jarg10, int jarg11, int jarg12, int jarg13, int jarg14, int jarg15, int jarg16); @@ -17185,18 +17177,18 @@ namespace FreeSWITCH.Native { using System; using System.Runtime.InteropServices; -public class SWIGTYPE_p_p_switch_cache_db_handle_t { +public class SWIGTYPE_p_p_switch_cache_db_handle { private HandleRef swigCPtr; - internal SWIGTYPE_p_p_switch_cache_db_handle_t(IntPtr cPtr, bool futureUse) { + internal SWIGTYPE_p_p_switch_cache_db_handle(IntPtr cPtr, bool futureUse) { swigCPtr = new HandleRef(this, cPtr); } - protected SWIGTYPE_p_p_switch_cache_db_handle_t() { + protected SWIGTYPE_p_p_switch_cache_db_handle() { swigCPtr = new HandleRef(null, IntPtr.Zero); } - internal static HandleRef getCPtr(SWIGTYPE_p_p_switch_cache_db_handle_t obj) { + internal static HandleRef getCPtr(SWIGTYPE_p_p_switch_cache_db_handle obj) { return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr; } } @@ -18205,6 +18197,36 @@ namespace FreeSWITCH.Native { using System; using System.Runtime.InteropServices; +public class SWIGTYPE_p_switch_cache_db_handle { + private HandleRef swigCPtr; + + internal SWIGTYPE_p_switch_cache_db_handle(IntPtr cPtr, bool futureUse) { + swigCPtr = new HandleRef(this, cPtr); + } + + protected SWIGTYPE_p_switch_cache_db_handle() { + swigCPtr = new HandleRef(null, IntPtr.Zero); + } + + internal static HandleRef getCPtr(SWIGTYPE_p_switch_cache_db_handle obj) { + return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr; + } +} + +} +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 2.0.1 + * + * Do not make changes to this file unless you know what you are doing--modify + * the SWIG interface file instead. + * ----------------------------------------------------------------------------- */ + +namespace FreeSWITCH.Native { + +using System; +using System.Runtime.InteropServices; + public class SWIGTYPE_p_switch_call_cause_t { private HandleRef swigCPtr; @@ -20687,171 +20709,6 @@ public class switch_cache_db_core_db_options_t : IDisposable { namespace FreeSWITCH.Native { -using System; -using System.Runtime.InteropServices; - -public class switch_cache_db_handle_t : IDisposable { - private HandleRef swigCPtr; - protected bool swigCMemOwn; - - internal switch_cache_db_handle_t(IntPtr cPtr, bool cMemoryOwn) { - swigCMemOwn = cMemoryOwn; - swigCPtr = new HandleRef(this, cPtr); - } - - internal static HandleRef getCPtr(switch_cache_db_handle_t obj) { - return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr; - } - - ~switch_cache_db_handle_t() { - Dispose(); - } - - public virtual void Dispose() { - lock(this) { - if (swigCPtr.Handle != IntPtr.Zero) { - if (swigCMemOwn) { - swigCMemOwn = false; - freeswitchPINVOKE.delete_switch_cache_db_handle_t(swigCPtr); - } - swigCPtr = new HandleRef(null, IntPtr.Zero); - } - GC.SuppressFinalize(this); - } - } - - public string name { - set { - freeswitchPINVOKE.switch_cache_db_handle_t_name_set(swigCPtr, value); - } - get { - string ret = freeswitchPINVOKE.switch_cache_db_handle_t_name_get(swigCPtr); - return ret; - } - } - - public switch_cache_db_handle_type_t type { - set { - freeswitchPINVOKE.switch_cache_db_handle_t_type_set(swigCPtr, (int)value); - } - get { - switch_cache_db_handle_type_t ret = (switch_cache_db_handle_type_t)freeswitchPINVOKE.switch_cache_db_handle_t_type_get(swigCPtr); - return ret; - } - } - - public switch_cache_db_native_handle_t native_handle { - set { - freeswitchPINVOKE.switch_cache_db_handle_t_native_handle_set(swigCPtr, switch_cache_db_native_handle_t.getCPtr(value)); - } - get { - IntPtr cPtr = freeswitchPINVOKE.switch_cache_db_handle_t_native_handle_get(swigCPtr); - switch_cache_db_native_handle_t ret = (cPtr == IntPtr.Zero) ? null : new switch_cache_db_native_handle_t(cPtr, false); - return ret; - } - } - - public SWIGTYPE_p_time_t last_used { - set { - freeswitchPINVOKE.switch_cache_db_handle_t_last_used_set(swigCPtr, SWIGTYPE_p_time_t.getCPtr(value)); - if (freeswitchPINVOKE.SWIGPendingException.Pending) throw freeswitchPINVOKE.SWIGPendingException.Retrieve(); - } - get { - SWIGTYPE_p_time_t ret = new SWIGTYPE_p_time_t(freeswitchPINVOKE.switch_cache_db_handle_t_last_used_get(swigCPtr), true); - if (freeswitchPINVOKE.SWIGPendingException.Pending) throw freeswitchPINVOKE.SWIGPendingException.Retrieve(); - return ret; - } - } - - public SWIGTYPE_p_switch_mutex_t mutex { - set { - freeswitchPINVOKE.switch_cache_db_handle_t_mutex_set(swigCPtr, SWIGTYPE_p_switch_mutex_t.getCPtr(value)); - } - get { - IntPtr cPtr = freeswitchPINVOKE.switch_cache_db_handle_t_mutex_get(swigCPtr); - SWIGTYPE_p_switch_mutex_t ret = (cPtr == IntPtr.Zero) ? null : new SWIGTYPE_p_switch_mutex_t(cPtr, false); - return ret; - } - } - - public SWIGTYPE_p_switch_mutex_t io_mutex { - set { - freeswitchPINVOKE.switch_cache_db_handle_t_io_mutex_set(swigCPtr, SWIGTYPE_p_switch_mutex_t.getCPtr(value)); - } - get { - IntPtr cPtr = freeswitchPINVOKE.switch_cache_db_handle_t_io_mutex_get(swigCPtr); - SWIGTYPE_p_switch_mutex_t ret = (cPtr == IntPtr.Zero) ? null : new SWIGTYPE_p_switch_mutex_t(cPtr, false); - return ret; - } - } - - public SWIGTYPE_p_apr_pool_t pool { - set { - freeswitchPINVOKE.switch_cache_db_handle_t_pool_set(swigCPtr, SWIGTYPE_p_apr_pool_t.getCPtr(value)); - } - get { - IntPtr cPtr = freeswitchPINVOKE.switch_cache_db_handle_t_pool_get(swigCPtr); - SWIGTYPE_p_apr_pool_t ret = (cPtr == IntPtr.Zero) ? null : new SWIGTYPE_p_apr_pool_t(cPtr, false); - return ret; - } - } - - public int flags { - set { - freeswitchPINVOKE.switch_cache_db_handle_t_flags_set(swigCPtr, value); - } - get { - int ret = freeswitchPINVOKE.switch_cache_db_handle_t_flags_get(swigCPtr); - return ret; - } - } - - public uint hash { - set { - freeswitchPINVOKE.switch_cache_db_handle_t_hash_set(swigCPtr, value); - } - get { - uint ret = freeswitchPINVOKE.switch_cache_db_handle_t_hash_get(swigCPtr); - return ret; - } - } - - public string creator { - set { - freeswitchPINVOKE.switch_cache_db_handle_t_creator_set(swigCPtr, value); - } - get { - string ret = freeswitchPINVOKE.switch_cache_db_handle_t_creator_get(swigCPtr); - return ret; - } - } - - public string last_user { - set { - freeswitchPINVOKE.switch_cache_db_handle_t_last_user_set(swigCPtr, value); - } - get { - string ret = freeswitchPINVOKE.switch_cache_db_handle_t_last_user_get(swigCPtr); - return ret; - } - } - - public switch_cache_db_handle_t() : this(freeswitchPINVOKE.new_switch_cache_db_handle_t(), true) { - } - -} - -} -/* ---------------------------------------------------------------------------- - * This file was automatically generated by SWIG (http://www.swig.org). - * Version 2.0.1 - * - * Do not make changes to this file unless you know what you are doing--modify - * the SWIG interface file instead. - * ----------------------------------------------------------------------------- */ - -namespace FreeSWITCH.Native { - public enum switch_cache_db_handle_type_t { SCDB_TYPE_CORE_DB, SCDB_TYPE_ODBC @@ -24977,6 +24834,8 @@ public enum switch_event_types_t { SWITCH_EVENT_NAT, SWITCH_EVENT_RECORD_START, SWITCH_EVENT_RECORD_STOP, + SWITCH_EVENT_PLAYBACK_START, + SWITCH_EVENT_PLAYBACK_STOP, SWITCH_EVENT_CALL_UPDATE, SWITCH_EVENT_FAILURE, SWITCH_EVENT_SOCKET_DATA, diff --git a/src/mod/languages/mod_managed/managed/swig.cs b/src/mod/languages/mod_managed/managed/swig.cs index c640199353..ac472af502 100644 --- a/src/mod/languages/mod_managed/managed/swig.cs +++ b/src/mod/languages/mod_managed/managed/swig.cs @@ -1384,6 +1384,21 @@ public class freeswitch { return ret; } + public static string switch_core_get_variable_dup(string varname) { + string ret = freeswitchPINVOKE.switch_core_get_variable_dup(varname); + return ret; + } + + public static string switch_core_get_variable_pdup(string varname, SWIGTYPE_p_apr_pool_t pool) { + string ret = freeswitchPINVOKE.switch_core_get_variable_pdup(varname, SWIGTYPE_p_apr_pool_t.getCPtr(pool)); + return ret; + } + + public static string switch_core_get_hostname() { + string ret = freeswitchPINVOKE.switch_core_get_hostname(); + return ret; + } + public static void switch_core_set_variable(string varname, string value) { freeswitchPINVOKE.switch_core_set_variable(varname, value); } @@ -2326,40 +2341,41 @@ public class freeswitch { return ret; } - public static void switch_cache_db_dismiss_db_handle(SWIGTYPE_p_p_switch_cache_db_handle_t dbh) { - freeswitchPINVOKE.switch_cache_db_dismiss_db_handle(SWIGTYPE_p_p_switch_cache_db_handle_t.getCPtr(dbh)); - } - - public static void switch_cache_db_release_db_handle(SWIGTYPE_p_p_switch_cache_db_handle_t dbh) { - freeswitchPINVOKE.switch_cache_db_release_db_handle(SWIGTYPE_p_p_switch_cache_db_handle_t.getCPtr(dbh)); - } - - public static void switch_cache_db_destroy_db_handle(SWIGTYPE_p_p_switch_cache_db_handle_t dbh) { - freeswitchPINVOKE.switch_cache_db_destroy_db_handle(SWIGTYPE_p_p_switch_cache_db_handle_t.getCPtr(dbh)); - } - - public static switch_status_t _switch_cache_db_get_db_handle(SWIGTYPE_p_p_switch_cache_db_handle_t dbh, switch_cache_db_handle_type_t type, switch_cache_db_connection_options_t connection_options, string file, string func, int line) { - switch_status_t ret = (switch_status_t)freeswitchPINVOKE._switch_cache_db_get_db_handle(SWIGTYPE_p_p_switch_cache_db_handle_t.getCPtr(dbh), (int)type, switch_cache_db_connection_options_t.getCPtr(connection_options), file, func, line); + public static switch_cache_db_handle_type_t switch_cache_db_get_type(SWIGTYPE_p_switch_cache_db_handle dbh) { + switch_cache_db_handle_type_t ret = (switch_cache_db_handle_type_t)freeswitchPINVOKE.switch_cache_db_get_type(SWIGTYPE_p_switch_cache_db_handle.getCPtr(dbh)); return ret; } - public static string switch_cache_db_execute_sql2str(switch_cache_db_handle_t dbh, string sql, string str, uint len, ref string err) { - string ret = freeswitchPINVOKE.switch_cache_db_execute_sql2str(switch_cache_db_handle_t.getCPtr(dbh), sql, str, len, ref err); + public static void switch_cache_db_dismiss_db_handle(SWIGTYPE_p_p_switch_cache_db_handle dbh) { + freeswitchPINVOKE.switch_cache_db_dismiss_db_handle(SWIGTYPE_p_p_switch_cache_db_handle.getCPtr(dbh)); + } + + public static void switch_cache_db_release_db_handle(SWIGTYPE_p_p_switch_cache_db_handle dbh) { + freeswitchPINVOKE.switch_cache_db_release_db_handle(SWIGTYPE_p_p_switch_cache_db_handle.getCPtr(dbh)); + } + + public static switch_status_t _switch_cache_db_get_db_handle(SWIGTYPE_p_p_switch_cache_db_handle dbh, switch_cache_db_handle_type_t type, switch_cache_db_connection_options_t connection_options, string file, string func, int line) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE._switch_cache_db_get_db_handle(SWIGTYPE_p_p_switch_cache_db_handle.getCPtr(dbh), (int)type, switch_cache_db_connection_options_t.getCPtr(connection_options), file, func, line); return ret; } - public static switch_status_t switch_cache_db_execute_sql(switch_cache_db_handle_t dbh, string sql, ref string err) { - switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_cache_db_execute_sql(switch_cache_db_handle_t.getCPtr(dbh), sql, ref err); + public static string switch_cache_db_execute_sql2str(SWIGTYPE_p_switch_cache_db_handle dbh, string sql, string str, uint len, ref string err) { + string ret = freeswitchPINVOKE.switch_cache_db_execute_sql2str(SWIGTYPE_p_switch_cache_db_handle.getCPtr(dbh), sql, str, len, ref err); return ret; } - public static switch_status_t switch_cache_db_execute_sql_callback(switch_cache_db_handle_t dbh, string sql, SWIGTYPE_p_f_p_void_int_p_p_char_p_p_char__int callback, SWIGTYPE_p_void pdata, ref string err) { - switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_cache_db_execute_sql_callback(switch_cache_db_handle_t.getCPtr(dbh), sql, SWIGTYPE_p_f_p_void_int_p_p_char_p_p_char__int.getCPtr(callback), SWIGTYPE_p_void.getCPtr(pdata), ref err); + public static switch_status_t switch_cache_db_execute_sql(SWIGTYPE_p_switch_cache_db_handle dbh, string sql, ref string err) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_cache_db_execute_sql(SWIGTYPE_p_switch_cache_db_handle.getCPtr(dbh), sql, ref err); return ret; } - public static int switch_cache_db_affected_rows(switch_cache_db_handle_t dbh) { - int ret = freeswitchPINVOKE.switch_cache_db_affected_rows(switch_cache_db_handle_t.getCPtr(dbh)); + public static switch_status_t switch_cache_db_execute_sql_callback(SWIGTYPE_p_switch_cache_db_handle dbh, string sql, SWIGTYPE_p_f_p_void_int_p_p_char_p_p_char__int callback, SWIGTYPE_p_void pdata, ref string err) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_cache_db_execute_sql_callback(SWIGTYPE_p_switch_cache_db_handle.getCPtr(dbh), sql, SWIGTYPE_p_f_p_void_int_p_p_char_p_p_char__int.getCPtr(callback), SWIGTYPE_p_void.getCPtr(pdata), ref err); + return ret; + } + + public static int switch_cache_db_affected_rows(SWIGTYPE_p_switch_cache_db_handle dbh) { + int ret = freeswitchPINVOKE.switch_cache_db_affected_rows(SWIGTYPE_p_switch_cache_db_handle.getCPtr(dbh)); return ret; } @@ -2367,30 +2383,26 @@ public class freeswitch { freeswitchPINVOKE.switch_cache_db_status(switch_stream_handle.getCPtr(stream)); } - public static switch_status_t _switch_core_db_handle(SWIGTYPE_p_p_switch_cache_db_handle_t dbh, string file, string func, int line) { - switch_status_t ret = (switch_status_t)freeswitchPINVOKE._switch_core_db_handle(SWIGTYPE_p_p_switch_cache_db_handle_t.getCPtr(dbh), file, func, line); + public static switch_status_t _switch_core_db_handle(SWIGTYPE_p_p_switch_cache_db_handle dbh, string file, string func, int line) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE._switch_core_db_handle(SWIGTYPE_p_p_switch_cache_db_handle.getCPtr(dbh), file, func, line); return ret; } - public static switch_bool_t switch_cache_db_test_reactive(switch_cache_db_handle_t db, string test_sql, string drop_sql, string reactive_sql) { - switch_bool_t ret = (switch_bool_t)freeswitchPINVOKE.switch_cache_db_test_reactive(switch_cache_db_handle_t.getCPtr(db), test_sql, drop_sql, reactive_sql); + public static switch_bool_t switch_cache_db_test_reactive(SWIGTYPE_p_switch_cache_db_handle db, string test_sql, string drop_sql, string reactive_sql) { + switch_bool_t ret = (switch_bool_t)freeswitchPINVOKE.switch_cache_db_test_reactive(SWIGTYPE_p_switch_cache_db_handle.getCPtr(db), test_sql, drop_sql, reactive_sql); return ret; } - public static switch_status_t switch_cache_db_persistant_execute(switch_cache_db_handle_t dbh, string sql, uint retries) { - switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_cache_db_persistant_execute(switch_cache_db_handle_t.getCPtr(dbh), sql, retries); + public static switch_status_t switch_cache_db_persistant_execute(SWIGTYPE_p_switch_cache_db_handle dbh, string sql, uint retries) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_cache_db_persistant_execute(SWIGTYPE_p_switch_cache_db_handle.getCPtr(dbh), sql, retries); return ret; } - public static switch_status_t switch_cache_db_persistant_execute_trans(switch_cache_db_handle_t dbh, string sql, uint retries) { - switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_cache_db_persistant_execute_trans(switch_cache_db_handle_t.getCPtr(dbh), sql, retries); + public static switch_status_t switch_cache_db_persistant_execute_trans(SWIGTYPE_p_switch_cache_db_handle dbh, string sql, uint retries) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_cache_db_persistant_execute_trans(SWIGTYPE_p_switch_cache_db_handle.getCPtr(dbh), sql, retries); return ret; } - public static void switch_cache_db_detach() { - freeswitchPINVOKE.switch_cache_db_detach(); - } - public static uint switch_core_debug_level() { uint ret = freeswitchPINVOKE.switch_core_debug_level(); return ret; @@ -2415,6 +2427,21 @@ public class freeswitch { return ret; } + public static switch_status_t switch_core_add_registration(string user, string realm, string token, string url, uint expires, string network_ip, string network_port, string network_proto) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_core_add_registration(user, realm, token, url, expires, network_ip, network_port, network_proto); + return ret; + } + + public static switch_status_t switch_core_del_registration(string user, string realm, string token) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_core_del_registration(user, realm, token); + return ret; + } + + public static switch_status_t switch_core_expire_registration(int force) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_core_expire_registration(force); + return ret; + } + public static switch_status_t switch_loadable_module_init(switch_bool_t autoload) { switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_loadable_module_init((int)autoload); return ret; @@ -3974,6 +4001,10 @@ public class freeswitch { freeswitchPINVOKE.switch_change_sln_volume(SWIGTYPE_p_short.getCPtr(data), samples, vol); } + public static void switch_change_sln_volume_granular(SWIGTYPE_p_short data, uint samples, int vol) { + freeswitchPINVOKE.switch_change_sln_volume_granular(SWIGTYPE_p_short.getCPtr(data), samples, vol); + } + public static uint switch_merge_sln(SWIGTYPE_p_short data, uint samples, SWIGTYPE_p_short other_data, uint other_samples) { uint ret = freeswitchPINVOKE.switch_merge_sln(SWIGTYPE_p_short.getCPtr(data), samples, SWIGTYPE_p_short.getCPtr(other_data), other_samples); return ret; @@ -4719,8 +4750,8 @@ public class freeswitch { return ret; } - public static switch_status_t switch_rtp_activate_jitter_buffer(SWIGTYPE_p_switch_rtp rtp_session, uint queue_frames, uint max_queue_frames, uint samples_per_packet, uint samples_per_second) { - switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_rtp_activate_jitter_buffer(SWIGTYPE_p_switch_rtp.getCPtr(rtp_session), queue_frames, max_queue_frames, samples_per_packet, samples_per_second); + public static switch_status_t switch_rtp_activate_jitter_buffer(SWIGTYPE_p_switch_rtp rtp_session, uint queue_frames, uint max_queue_frames, uint samples_per_packet, uint samples_per_second, uint max_drift) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_rtp_activate_jitter_buffer(SWIGTYPE_p_switch_rtp.getCPtr(rtp_session), queue_frames, max_queue_frames, samples_per_packet, samples_per_second, max_drift); return ret; } @@ -4857,6 +4888,10 @@ public class freeswitch { freeswitchPINVOKE.switch_rtp_set_telephony_recv_event(SWIGTYPE_p_switch_rtp.getCPtr(rtp_session), te); } + public static void switch_rtp_set_recv_pt(SWIGTYPE_p_switch_rtp rtp_session, byte pt) { + freeswitchPINVOKE.switch_rtp_set_recv_pt(SWIGTYPE_p_switch_rtp.getCPtr(rtp_session), pt); + } + public static void switch_rtp_set_cng_pt(SWIGTYPE_p_switch_rtp rtp_session, byte pt) { freeswitchPINVOKE.switch_rtp_set_cng_pt(SWIGTYPE_p_switch_rtp.getCPtr(rtp_session), pt); } @@ -7569,6 +7604,15 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_core_get_variable")] public static extern string switch_core_get_variable(string jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_get_variable_dup")] + public static extern string switch_core_get_variable_dup(string jarg1); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_get_variable_pdup")] + public static extern string switch_core_get_variable_pdup(string jarg1, HandleRef jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_get_hostname")] + public static extern string switch_core_get_hostname(); + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_set_variable")] public static extern void switch_core_set_variable(string jarg1, string jarg2); @@ -8217,90 +8261,18 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_delete_switch_cache_db_connection_options_t")] public static extern void delete_switch_cache_db_connection_options_t(HandleRef jarg1); - [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_handle_t_name_set")] - public static extern void switch_cache_db_handle_t_name_set(HandleRef jarg1, string jarg2); - - [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_handle_t_name_get")] - public static extern string switch_cache_db_handle_t_name_get(HandleRef jarg1); - - [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_handle_t_type_set")] - public static extern void switch_cache_db_handle_t_type_set(HandleRef jarg1, int jarg2); - - [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_handle_t_type_get")] - public static extern int switch_cache_db_handle_t_type_get(HandleRef jarg1); - - [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_handle_t_native_handle_set")] - public static extern void switch_cache_db_handle_t_native_handle_set(HandleRef jarg1, HandleRef jarg2); - - [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_handle_t_native_handle_get")] - public static extern IntPtr switch_cache_db_handle_t_native_handle_get(HandleRef jarg1); - - [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_handle_t_last_used_set")] - public static extern void switch_cache_db_handle_t_last_used_set(HandleRef jarg1, HandleRef jarg2); - - [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_handle_t_last_used_get")] - public static extern IntPtr switch_cache_db_handle_t_last_used_get(HandleRef jarg1); - - [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_handle_t_mutex_set")] - public static extern void switch_cache_db_handle_t_mutex_set(HandleRef jarg1, HandleRef jarg2); - - [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_handle_t_mutex_get")] - public static extern IntPtr switch_cache_db_handle_t_mutex_get(HandleRef jarg1); - - [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_handle_t_io_mutex_set")] - public static extern void switch_cache_db_handle_t_io_mutex_set(HandleRef jarg1, HandleRef jarg2); - - [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_handle_t_io_mutex_get")] - public static extern IntPtr switch_cache_db_handle_t_io_mutex_get(HandleRef jarg1); - - [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_handle_t_pool_set")] - public static extern void switch_cache_db_handle_t_pool_set(HandleRef jarg1, HandleRef jarg2); - - [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_handle_t_pool_get")] - public static extern IntPtr switch_cache_db_handle_t_pool_get(HandleRef jarg1); - - [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_handle_t_flags_set")] - public static extern void switch_cache_db_handle_t_flags_set(HandleRef jarg1, int jarg2); - - [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_handle_t_flags_get")] - public static extern int switch_cache_db_handle_t_flags_get(HandleRef jarg1); - - [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_handle_t_hash_set")] - public static extern void switch_cache_db_handle_t_hash_set(HandleRef jarg1, uint jarg2); - - [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_handle_t_hash_get")] - public static extern uint switch_cache_db_handle_t_hash_get(HandleRef jarg1); - - [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_handle_t_creator_set")] - public static extern void switch_cache_db_handle_t_creator_set(HandleRef jarg1, string jarg2); - - [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_handle_t_creator_get")] - public static extern string switch_cache_db_handle_t_creator_get(HandleRef jarg1); - - [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_handle_t_last_user_set")] - public static extern void switch_cache_db_handle_t_last_user_set(HandleRef jarg1, string jarg2); - - [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_handle_t_last_user_get")] - public static extern string switch_cache_db_handle_t_last_user_get(HandleRef jarg1); - - [DllImport("mod_managed", EntryPoint="CSharp_new_switch_cache_db_handle_t")] - public static extern IntPtr new_switch_cache_db_handle_t(); - - [DllImport("mod_managed", EntryPoint="CSharp_delete_switch_cache_db_handle_t")] - public static extern void delete_switch_cache_db_handle_t(HandleRef jarg1); - [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_type_name")] public static extern string switch_cache_db_type_name(int jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_get_type")] + public static extern int switch_cache_db_get_type(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_dismiss_db_handle")] public static extern void switch_cache_db_dismiss_db_handle(HandleRef jarg1); [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_release_db_handle")] public static extern void switch_cache_db_release_db_handle(HandleRef jarg1); - [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_destroy_db_handle")] - public static extern void switch_cache_db_destroy_db_handle(HandleRef jarg1); - [DllImport("mod_managed", EntryPoint="CSharp__switch_cache_db_get_db_handle")] public static extern int _switch_cache_db_get_db_handle(HandleRef jarg1, int jarg2, HandleRef jarg3, string jarg4, string jarg5, int jarg6); @@ -8331,9 +8303,6 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_persistant_execute_trans")] public static extern int switch_cache_db_persistant_execute_trans(HandleRef jarg1, string jarg2, uint jarg3); - [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_detach")] - public static extern void switch_cache_db_detach(); - [DllImport("mod_managed", EntryPoint="CSharp_switch_core_debug_level")] public static extern uint switch_core_debug_level(); @@ -8349,6 +8318,15 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_default_ptime")] public static extern uint switch_default_ptime(string jarg1, uint jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_add_registration")] + public static extern int switch_core_add_registration(string jarg1, string jarg2, string jarg3, string jarg4, uint jarg5, string jarg6, string jarg7, string jarg8); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_del_registration")] + public static extern int switch_core_del_registration(string jarg1, string jarg2, string jarg3); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_expire_registration")] + public static extern int switch_core_expire_registration(int jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_loadable_module_interface_module_name_set")] public static extern void switch_loadable_module_interface_module_name_set(HandleRef jarg1, string jarg2); @@ -12042,6 +12020,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_change_sln_volume")] public static extern void switch_change_sln_volume(HandleRef jarg1, uint jarg2, int jarg3); + [DllImport("mod_managed", EntryPoint="CSharp_switch_change_sln_volume_granular")] + public static extern void switch_change_sln_volume_granular(HandleRef jarg1, uint jarg2, int jarg3); + [DllImport("mod_managed", EntryPoint="CSharp_switch_merge_sln")] public static extern uint switch_merge_sln(HandleRef jarg1, uint jarg2, HandleRef jarg3, uint jarg4); @@ -12652,7 +12633,7 @@ class freeswitchPINVOKE { public static extern int switch_rtp_activate_rtcp(HandleRef jarg1, int jarg2, ushort jarg3); [DllImport("mod_managed", EntryPoint="CSharp_switch_rtp_activate_jitter_buffer")] - public static extern int switch_rtp_activate_jitter_buffer(HandleRef jarg1, uint jarg2, uint jarg3, uint jarg4, uint jarg5); + public static extern int switch_rtp_activate_jitter_buffer(HandleRef jarg1, uint jarg2, uint jarg3, uint jarg4, uint jarg5, uint jarg6); [DllImport("mod_managed", EntryPoint="CSharp_switch_rtp_debug_jitter_buffer")] public static extern int switch_rtp_debug_jitter_buffer(HandleRef jarg1, string jarg2); @@ -12738,6 +12719,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_rtp_set_telephony_recv_event")] public static extern void switch_rtp_set_telephony_recv_event(HandleRef jarg1, byte jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_rtp_set_recv_pt")] + public static extern void switch_rtp_set_recv_pt(HandleRef jarg1, byte jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_rtp_set_cng_pt")] public static extern void switch_rtp_set_cng_pt(HandleRef jarg1, byte jarg2); @@ -17139,18 +17123,18 @@ namespace FreeSWITCH.Native { using System; using System.Runtime.InteropServices; -public class SWIGTYPE_p_p_switch_cache_db_handle_t { +public class SWIGTYPE_p_p_switch_cache_db_handle { private HandleRef swigCPtr; - internal SWIGTYPE_p_p_switch_cache_db_handle_t(IntPtr cPtr, bool futureUse) { + internal SWIGTYPE_p_p_switch_cache_db_handle(IntPtr cPtr, bool futureUse) { swigCPtr = new HandleRef(this, cPtr); } - protected SWIGTYPE_p_p_switch_cache_db_handle_t() { + protected SWIGTYPE_p_p_switch_cache_db_handle() { swigCPtr = new HandleRef(null, IntPtr.Zero); } - internal static HandleRef getCPtr(SWIGTYPE_p_p_switch_cache_db_handle_t obj) { + internal static HandleRef getCPtr(SWIGTYPE_p_p_switch_cache_db_handle obj) { return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr; } } @@ -18159,6 +18143,36 @@ namespace FreeSWITCH.Native { using System; using System.Runtime.InteropServices; +public class SWIGTYPE_p_switch_cache_db_handle { + private HandleRef swigCPtr; + + internal SWIGTYPE_p_switch_cache_db_handle(IntPtr cPtr, bool futureUse) { + swigCPtr = new HandleRef(this, cPtr); + } + + protected SWIGTYPE_p_switch_cache_db_handle() { + swigCPtr = new HandleRef(null, IntPtr.Zero); + } + + internal static HandleRef getCPtr(SWIGTYPE_p_switch_cache_db_handle obj) { + return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr; + } +} + +} +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 1.3.35 + * + * Do not make changes to this file unless you know what you are doing--modify + * the SWIG interface file instead. + * ----------------------------------------------------------------------------- */ + +namespace FreeSWITCH.Native { + +using System; +using System.Runtime.InteropServices; + public class SWIGTYPE_p_switch_call_cause_t { private HandleRef swigCPtr; @@ -20653,169 +20667,6 @@ public class switch_cache_db_core_db_options_t : IDisposable { namespace FreeSWITCH.Native { -using System; -using System.Runtime.InteropServices; - -public class switch_cache_db_handle_t : IDisposable { - private HandleRef swigCPtr; - protected bool swigCMemOwn; - - internal switch_cache_db_handle_t(IntPtr cPtr, bool cMemoryOwn) { - swigCMemOwn = cMemoryOwn; - swigCPtr = new HandleRef(this, cPtr); - } - - internal static HandleRef getCPtr(switch_cache_db_handle_t obj) { - return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr; - } - - ~switch_cache_db_handle_t() { - Dispose(); - } - - public virtual void Dispose() { - lock(this) { - if(swigCPtr.Handle != IntPtr.Zero && swigCMemOwn) { - swigCMemOwn = false; - freeswitchPINVOKE.delete_switch_cache_db_handle_t(swigCPtr); - } - swigCPtr = new HandleRef(null, IntPtr.Zero); - GC.SuppressFinalize(this); - } - } - - public string name { - set { - freeswitchPINVOKE.switch_cache_db_handle_t_name_set(swigCPtr, value); - } - get { - string ret = freeswitchPINVOKE.switch_cache_db_handle_t_name_get(swigCPtr); - return ret; - } - } - - public switch_cache_db_handle_type_t type { - set { - freeswitchPINVOKE.switch_cache_db_handle_t_type_set(swigCPtr, (int)value); - } - get { - switch_cache_db_handle_type_t ret = (switch_cache_db_handle_type_t)freeswitchPINVOKE.switch_cache_db_handle_t_type_get(swigCPtr); - return ret; - } - } - - public switch_cache_db_native_handle_t native_handle { - set { - freeswitchPINVOKE.switch_cache_db_handle_t_native_handle_set(swigCPtr, switch_cache_db_native_handle_t.getCPtr(value)); - } - get { - IntPtr cPtr = freeswitchPINVOKE.switch_cache_db_handle_t_native_handle_get(swigCPtr); - switch_cache_db_native_handle_t ret = (cPtr == IntPtr.Zero) ? null : new switch_cache_db_native_handle_t(cPtr, false); - return ret; - } - } - - public SWIGTYPE_p_time_t last_used { - set { - freeswitchPINVOKE.switch_cache_db_handle_t_last_used_set(swigCPtr, SWIGTYPE_p_time_t.getCPtr(value)); - if (freeswitchPINVOKE.SWIGPendingException.Pending) throw freeswitchPINVOKE.SWIGPendingException.Retrieve(); - } - get { - SWIGTYPE_p_time_t ret = new SWIGTYPE_p_time_t(freeswitchPINVOKE.switch_cache_db_handle_t_last_used_get(swigCPtr), true); - if (freeswitchPINVOKE.SWIGPendingException.Pending) throw freeswitchPINVOKE.SWIGPendingException.Retrieve(); - return ret; - } - } - - public SWIGTYPE_p_switch_mutex_t mutex { - set { - freeswitchPINVOKE.switch_cache_db_handle_t_mutex_set(swigCPtr, SWIGTYPE_p_switch_mutex_t.getCPtr(value)); - } - get { - IntPtr cPtr = freeswitchPINVOKE.switch_cache_db_handle_t_mutex_get(swigCPtr); - SWIGTYPE_p_switch_mutex_t ret = (cPtr == IntPtr.Zero) ? null : new SWIGTYPE_p_switch_mutex_t(cPtr, false); - return ret; - } - } - - public SWIGTYPE_p_switch_mutex_t io_mutex { - set { - freeswitchPINVOKE.switch_cache_db_handle_t_io_mutex_set(swigCPtr, SWIGTYPE_p_switch_mutex_t.getCPtr(value)); - } - get { - IntPtr cPtr = freeswitchPINVOKE.switch_cache_db_handle_t_io_mutex_get(swigCPtr); - SWIGTYPE_p_switch_mutex_t ret = (cPtr == IntPtr.Zero) ? null : new SWIGTYPE_p_switch_mutex_t(cPtr, false); - return ret; - } - } - - public SWIGTYPE_p_apr_pool_t pool { - set { - freeswitchPINVOKE.switch_cache_db_handle_t_pool_set(swigCPtr, SWIGTYPE_p_apr_pool_t.getCPtr(value)); - } - get { - IntPtr cPtr = freeswitchPINVOKE.switch_cache_db_handle_t_pool_get(swigCPtr); - SWIGTYPE_p_apr_pool_t ret = (cPtr == IntPtr.Zero) ? null : new SWIGTYPE_p_apr_pool_t(cPtr, false); - return ret; - } - } - - public int flags { - set { - freeswitchPINVOKE.switch_cache_db_handle_t_flags_set(swigCPtr, value); - } - get { - int ret = freeswitchPINVOKE.switch_cache_db_handle_t_flags_get(swigCPtr); - return ret; - } - } - - public uint hash { - set { - freeswitchPINVOKE.switch_cache_db_handle_t_hash_set(swigCPtr, value); - } - get { - uint ret = freeswitchPINVOKE.switch_cache_db_handle_t_hash_get(swigCPtr); - return ret; - } - } - - public string creator { - set { - freeswitchPINVOKE.switch_cache_db_handle_t_creator_set(swigCPtr, value); - } - get { - string ret = freeswitchPINVOKE.switch_cache_db_handle_t_creator_get(swigCPtr); - return ret; - } - } - - public string last_user { - set { - freeswitchPINVOKE.switch_cache_db_handle_t_last_user_set(swigCPtr, value); - } - get { - string ret = freeswitchPINVOKE.switch_cache_db_handle_t_last_user_get(swigCPtr); - return ret; - } - } - - public switch_cache_db_handle_t() : this(freeswitchPINVOKE.new_switch_cache_db_handle_t(), true) { - } - -} - -} -/* ---------------------------------------------------------------------------- - * This file was automatically generated by SWIG (http://www.swig.org). - * Version 1.3.35 - * - * Do not make changes to this file unless you know what you are doing--modify - * the SWIG interface file instead. - * ----------------------------------------------------------------------------- */ - -namespace FreeSWITCH.Native { - public enum switch_cache_db_handle_type_t { SCDB_TYPE_CORE_DB, SCDB_TYPE_ODBC @@ -24889,6 +24740,8 @@ public enum switch_event_types_t { SWITCH_EVENT_NAT, SWITCH_EVENT_RECORD_START, SWITCH_EVENT_RECORD_STOP, + SWITCH_EVENT_PLAYBACK_START, + SWITCH_EVENT_PLAYBACK_STOP, SWITCH_EVENT_CALL_UPDATE, SWITCH_EVENT_FAILURE, SWITCH_EVENT_SOCKET_DATA, diff --git a/src/mod/languages/mod_perl/freeswitch.pm b/src/mod/languages/mod_perl/freeswitch.pm index cb31101489..e55ffac7de 100644 --- a/src/mod/languages/mod_perl/freeswitch.pm +++ b/src/mod/languages/mod_perl/freeswitch.pm @@ -50,6 +50,7 @@ package freeswitch; *consoleLog = *freeswitchc::consoleLog; *consoleCleanLog = *freeswitchc::consoleCleanLog; +*email = *freeswitchc::email; *console_log = *freeswitchc::console_log; *console_clean_log = *freeswitchc::console_clean_log; *msleep = *freeswitchc::msleep; diff --git a/src/mod/languages/mod_perl/mod_perl_wrap.cpp b/src/mod/languages/mod_perl/mod_perl_wrap.cpp index e8a4b9f409..079bec0866 100644 --- a/src/mod/languages/mod_perl/mod_perl_wrap.cpp +++ b/src/mod/languages/mod_perl/mod_perl_wrap.cpp @@ -1566,6 +1566,19 @@ SWIG_AsCharPtrAndSize(SV *obj, char** cptr, size_t* psize, int *alloc) +SWIGINTERNINLINE SV * +SWIG_From_bool SWIG_PERL_DECL_ARGS_1(bool value) +{ + SV *obj = sv_newmortal(); + if (value) { + sv_setsv(obj, &PL_sv_yes); + } else { + sv_setsv(obj, &PL_sv_no); + } + return obj; +} + + #include #if !defined(SWIG_NO_LLONG_MAX) # if !defined(LLONG_MAX) && defined(__GNUC__) && defined (__LONG_LONG_MAX__) @@ -1780,19 +1793,6 @@ SWIG_From_char SWIG_PERL_DECL_ARGS_1(char c) } -SWIGINTERNINLINE SV * -SWIG_From_bool SWIG_PERL_DECL_ARGS_1(bool value) -{ - SV *obj = sv_newmortal(); - if (value) { - sv_setsv(obj, &PL_sv_yes); - } else { - sv_setsv(obj, &PL_sv_no); - } - return obj; -} - - SWIGINTERN int SWIG_AsVal_unsigned_SS_long SWIG_PERL_DECL_ARGS_2(SV *obj, unsigned long *val) { @@ -1982,6 +1982,111 @@ XS(_wrap_consoleCleanLog) { } +XS(_wrap_email) { + { + char *arg1 = (char *) 0 ; + char *arg2 = (char *) 0 ; + char *arg3 = (char *) NULL ; + char *arg4 = (char *) NULL ; + char *arg5 = (char *) NULL ; + char *arg6 = (char *) NULL ; + char *arg7 = (char *) NULL ; + bool result; + int res1 ; + char *buf1 = 0 ; + int alloc1 = 0 ; + int res2 ; + char *buf2 = 0 ; + int alloc2 = 0 ; + int res3 ; + char *buf3 = 0 ; + int alloc3 = 0 ; + int res4 ; + char *buf4 = 0 ; + int alloc4 = 0 ; + int res5 ; + char *buf5 = 0 ; + int alloc5 = 0 ; + int res6 ; + char *buf6 = 0 ; + int alloc6 = 0 ; + int res7 ; + char *buf7 = 0 ; + int alloc7 = 0 ; + int argvi = 0; + dXSARGS; + + if ((items < 2) || (items > 7)) { + SWIG_croak("Usage: email(to,from,headers,body,file,convert_cmd,convert_ext);"); + } + res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "email" "', argument " "1"" of type '" "char *""'"); + } + arg1 = reinterpret_cast< char * >(buf1); + res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "email" "', argument " "2"" of type '" "char *""'"); + } + arg2 = reinterpret_cast< char * >(buf2); + if (items > 2) { + res3 = SWIG_AsCharPtrAndSize(ST(2), &buf3, NULL, &alloc3); + if (!SWIG_IsOK(res3)) { + SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "email" "', argument " "3"" of type '" "char *""'"); + } + arg3 = reinterpret_cast< char * >(buf3); + } + if (items > 3) { + res4 = SWIG_AsCharPtrAndSize(ST(3), &buf4, NULL, &alloc4); + if (!SWIG_IsOK(res4)) { + SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "email" "', argument " "4"" of type '" "char *""'"); + } + arg4 = reinterpret_cast< char * >(buf4); + } + if (items > 4) { + res5 = SWIG_AsCharPtrAndSize(ST(4), &buf5, NULL, &alloc5); + if (!SWIG_IsOK(res5)) { + SWIG_exception_fail(SWIG_ArgError(res5), "in method '" "email" "', argument " "5"" of type '" "char *""'"); + } + arg5 = reinterpret_cast< char * >(buf5); + } + if (items > 5) { + res6 = SWIG_AsCharPtrAndSize(ST(5), &buf6, NULL, &alloc6); + if (!SWIG_IsOK(res6)) { + SWIG_exception_fail(SWIG_ArgError(res6), "in method '" "email" "', argument " "6"" of type '" "char *""'"); + } + arg6 = reinterpret_cast< char * >(buf6); + } + if (items > 6) { + res7 = SWIG_AsCharPtrAndSize(ST(6), &buf7, NULL, &alloc7); + if (!SWIG_IsOK(res7)) { + SWIG_exception_fail(SWIG_ArgError(res7), "in method '" "email" "', argument " "7"" of type '" "char *""'"); + } + arg7 = reinterpret_cast< char * >(buf7); + } + result = (bool)email(arg1,arg2,arg3,arg4,arg5,arg6,arg7); + ST(argvi) = SWIG_From_bool SWIG_PERL_CALL_ARGS_1(static_cast< bool >(result)); argvi++ ; + if (alloc1 == SWIG_NEWOBJ) delete[] buf1; + if (alloc2 == SWIG_NEWOBJ) delete[] buf2; + if (alloc3 == SWIG_NEWOBJ) delete[] buf3; + if (alloc4 == SWIG_NEWOBJ) delete[] buf4; + if (alloc5 == SWIG_NEWOBJ) delete[] buf5; + if (alloc6 == SWIG_NEWOBJ) delete[] buf6; + if (alloc7 == SWIG_NEWOBJ) delete[] buf7; + XSRETURN(argvi); + fail: + if (alloc1 == SWIG_NEWOBJ) delete[] buf1; + if (alloc2 == SWIG_NEWOBJ) delete[] buf2; + if (alloc3 == SWIG_NEWOBJ) delete[] buf3; + if (alloc4 == SWIG_NEWOBJ) delete[] buf4; + if (alloc5 == SWIG_NEWOBJ) delete[] buf5; + if (alloc6 == SWIG_NEWOBJ) delete[] buf6; + if (alloc7 == SWIG_NEWOBJ) delete[] buf7; + SWIG_croak_null(); + } +} + + XS(_wrap_new_IVRMenu) { { IVRMenu *arg1 = (IVRMenu *) 0 ; @@ -9336,6 +9441,7 @@ static swig_variable_info swig_variables[] = { static swig_command_info swig_commands[] = { {"freeswitchc::consoleLog", _wrap_consoleLog}, {"freeswitchc::consoleCleanLog", _wrap_consoleCleanLog}, +{"freeswitchc::email", _wrap_email}, {"freeswitchc::new_IVRMenu", _wrap_new_IVRMenu}, {"freeswitchc::delete_IVRMenu", _wrap_delete_IVRMenu}, {"freeswitchc::IVRMenu_bindAction", _wrap_IVRMenu_bindAction}, diff --git a/src/mod/languages/mod_python/freeswitch.py b/src/mod/languages/mod_python/freeswitch.py index 03deb31d13..d49016d305 100644 --- a/src/mod/languages/mod_python/freeswitch.py +++ b/src/mod/languages/mod_python/freeswitch.py @@ -50,6 +50,7 @@ del types consoleLog = _freeswitch.consoleLog consoleCleanLog = _freeswitch.consoleCleanLog +email = _freeswitch.email class IVRMenu(_object): __swig_setmethods__ = {} __setattr__ = lambda self, name, value: _swig_setattr(self, IVRMenu, name, value) diff --git a/src/mod/languages/mod_python/mod_python_wrap.cpp b/src/mod/languages/mod_python/mod_python_wrap.cpp index 3326a19dcd..ccb5cac78e 100644 --- a/src/mod/languages/mod_python/mod_python_wrap.cpp +++ b/src/mod/languages/mod_python/mod_python_wrap.cpp @@ -2687,6 +2687,13 @@ SWIG_AsCharPtrAndSize(PyObject *obj, char** cptr, size_t* psize, int *alloc) +SWIGINTERNINLINE PyObject* + SWIG_From_bool (bool value) +{ + return PyBool_FromLong(value ? 1 : 0); +} + + #include #if !defined(SWIG_NO_LLONG_MAX) # if !defined(LLONG_MAX) && defined(__GNUC__) && defined (__LONG_LONG_MAX__) @@ -2916,13 +2923,6 @@ SWIG_From_char (char c) } -SWIGINTERNINLINE PyObject* - SWIG_From_bool (bool value) -{ - return PyBool_FromLong(value ? 1 : 0); -} - - SWIGINTERN int SWIG_AsVal_unsigned_SS_long (PyObject *obj, unsigned long *val) { @@ -3071,6 +3071,113 @@ fail: } +SWIGINTERN PyObject *_wrap_email(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + char *arg1 = (char *) 0 ; + char *arg2 = (char *) 0 ; + char *arg3 = (char *) NULL ; + char *arg4 = (char *) NULL ; + char *arg5 = (char *) NULL ; + char *arg6 = (char *) NULL ; + char *arg7 = (char *) NULL ; + bool result; + int res1 ; + char *buf1 = 0 ; + int alloc1 = 0 ; + int res2 ; + char *buf2 = 0 ; + int alloc2 = 0 ; + int res3 ; + char *buf3 = 0 ; + int alloc3 = 0 ; + int res4 ; + char *buf4 = 0 ; + int alloc4 = 0 ; + int res5 ; + char *buf5 = 0 ; + int alloc5 = 0 ; + int res6 ; + char *buf6 = 0 ; + int alloc6 = 0 ; + int res7 ; + char *buf7 = 0 ; + int alloc7 = 0 ; + PyObject * obj0 = 0 ; + PyObject * obj1 = 0 ; + PyObject * obj2 = 0 ; + PyObject * obj3 = 0 ; + PyObject * obj4 = 0 ; + PyObject * obj5 = 0 ; + PyObject * obj6 = 0 ; + + if (!PyArg_ParseTuple(args,(char *)"OO|OOOOO:email",&obj0,&obj1,&obj2,&obj3,&obj4,&obj5,&obj6)) SWIG_fail; + res1 = SWIG_AsCharPtrAndSize(obj0, &buf1, NULL, &alloc1); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "email" "', argument " "1"" of type '" "char *""'"); + } + arg1 = reinterpret_cast< char * >(buf1); + res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "email" "', argument " "2"" of type '" "char *""'"); + } + arg2 = reinterpret_cast< char * >(buf2); + if (obj2) { + res3 = SWIG_AsCharPtrAndSize(obj2, &buf3, NULL, &alloc3); + if (!SWIG_IsOK(res3)) { + SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "email" "', argument " "3"" of type '" "char *""'"); + } + arg3 = reinterpret_cast< char * >(buf3); + } + if (obj3) { + res4 = SWIG_AsCharPtrAndSize(obj3, &buf4, NULL, &alloc4); + if (!SWIG_IsOK(res4)) { + SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "email" "', argument " "4"" of type '" "char *""'"); + } + arg4 = reinterpret_cast< char * >(buf4); + } + if (obj4) { + res5 = SWIG_AsCharPtrAndSize(obj4, &buf5, NULL, &alloc5); + if (!SWIG_IsOK(res5)) { + SWIG_exception_fail(SWIG_ArgError(res5), "in method '" "email" "', argument " "5"" of type '" "char *""'"); + } + arg5 = reinterpret_cast< char * >(buf5); + } + if (obj5) { + res6 = SWIG_AsCharPtrAndSize(obj5, &buf6, NULL, &alloc6); + if (!SWIG_IsOK(res6)) { + SWIG_exception_fail(SWIG_ArgError(res6), "in method '" "email" "', argument " "6"" of type '" "char *""'"); + } + arg6 = reinterpret_cast< char * >(buf6); + } + if (obj6) { + res7 = SWIG_AsCharPtrAndSize(obj6, &buf7, NULL, &alloc7); + if (!SWIG_IsOK(res7)) { + SWIG_exception_fail(SWIG_ArgError(res7), "in method '" "email" "', argument " "7"" of type '" "char *""'"); + } + arg7 = reinterpret_cast< char * >(buf7); + } + result = (bool)email(arg1,arg2,arg3,arg4,arg5,arg6,arg7); + resultobj = SWIG_From_bool(static_cast< bool >(result)); + if (alloc1 == SWIG_NEWOBJ) delete[] buf1; + if (alloc2 == SWIG_NEWOBJ) delete[] buf2; + if (alloc3 == SWIG_NEWOBJ) delete[] buf3; + if (alloc4 == SWIG_NEWOBJ) delete[] buf4; + if (alloc5 == SWIG_NEWOBJ) delete[] buf5; + if (alloc6 == SWIG_NEWOBJ) delete[] buf6; + if (alloc7 == SWIG_NEWOBJ) delete[] buf7; + return resultobj; +fail: + if (alloc1 == SWIG_NEWOBJ) delete[] buf1; + if (alloc2 == SWIG_NEWOBJ) delete[] buf2; + if (alloc3 == SWIG_NEWOBJ) delete[] buf3; + if (alloc4 == SWIG_NEWOBJ) delete[] buf4; + if (alloc5 == SWIG_NEWOBJ) delete[] buf5; + if (alloc6 == SWIG_NEWOBJ) delete[] buf6; + if (alloc7 == SWIG_NEWOBJ) delete[] buf7; + return NULL; +} + + SWIGINTERN PyObject *_wrap_new_IVRMenu(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { PyObject *resultobj = 0; IVRMenu *arg1 = (IVRMenu *) 0 ; @@ -8878,6 +8985,7 @@ SWIGINTERN PyObject *Session_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObje static PyMethodDef SwigMethods[] = { { (char *)"consoleLog", _wrap_consoleLog, METH_VARARGS, NULL}, { (char *)"consoleCleanLog", _wrap_consoleCleanLog, METH_VARARGS, NULL}, + { (char *)"email", _wrap_email, METH_VARARGS, NULL}, { (char *)"new_IVRMenu", _wrap_new_IVRMenu, METH_VARARGS, NULL}, { (char *)"delete_IVRMenu", _wrap_delete_IVRMenu, METH_VARARGS, NULL}, { (char *)"IVRMenu_bindAction", _wrap_IVRMenu_bindAction, METH_VARARGS, NULL}, diff --git a/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c b/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c index a818c1dcd1..1a57f5f2ae 100644 --- a/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c +++ b/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c @@ -2882,8 +2882,8 @@ static JSBool session_construct(JSContext * cx, JSObject * obj, uintN argc, jsva if (switch_ivr_originate(old_jss ? old_jss->session : NULL, &jss->session, &jss->cause, uuid, 60, NULL, NULL, NULL, NULL, NULL, SOF_NONE, NULL) == SWITCH_STATUS_SUCCESS) { switch_set_flag(jss, S_HUP); - switch_channel_set_state(switch_core_session_get_channel(jss->session), CS_SOFT_EXECUTE); - switch_channel_wait_for_state_timeout(switch_core_session_get_channel(jss->session), CS_SOFT_EXECUTE, 5000); + //switch_channel_set_state(switch_core_session_get_channel(jss->session), CS_SOFT_EXECUTE); + //switch_channel_wait_for_state_timeout(switch_core_session_get_channel(jss->session), CS_SOFT_EXECUTE, 5000); *rval = BOOLEAN_TO_JSVAL(JS_TRUE); } else { *rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, switch_channel_cause2str(jss->cause))); @@ -3054,7 +3054,7 @@ static JSBool session_originate(JSContext * cx, JSObject * obj, uintN argc, jsva jss->session = peer_session; switch_set_flag(jss, S_HUP); *rval = BOOLEAN_TO_JSVAL(JS_TRUE); - switch_channel_set_state(switch_core_session_get_channel(jss->session), CS_SOFT_EXECUTE); + //switch_channel_set_state(switch_core_session_get_channel(jss->session), CS_SOFT_EXECUTE); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Missing Args\n"); diff --git a/src/mod/sdk/autotools/.gitignore b/src/mod/sdk/autotools/.gitignore new file mode 100644 index 0000000000..57b51acef5 --- /dev/null +++ b/src/mod/sdk/autotools/.gitignore @@ -0,0 +1,35 @@ +*.o +*.lo +*.so +*.a +*.orig +*.rej +*.log +*.la + +.deps +.libs + +stamp-h1 +samples* +Makefile +Makefile.in +config.log +config.sub +config.guess +config.status +configure +libtool +aclocal.m4 +autom4te.cache +depcomp +install-sh +compile +missing +ltmain.sh +doxygen +m4/libtool.m4 +m4/ltsugar.m4 +m4/ltoptions.m4 +m4/ltversion.m4 +m4/lt~obsolete.m4 diff --git a/src/mod/sdk/autotools/Makefile.am b/src/mod/sdk/autotools/Makefile.am new file mode 100644 index 0000000000..8f8a25a048 --- /dev/null +++ b/src/mod/sdk/autotools/Makefile.am @@ -0,0 +1,4 @@ +ACLOCAL_AMFLAGS = -I m4 +AUTOMAKE_OPTIONS = foreign no-dist subdir-objects + +SUBDIRS = src diff --git a/src/mod/sdk/autotools/autogen.sh b/src/mod/sdk/autotools/autogen.sh new file mode 100755 index 0000000000..08240fdfcd --- /dev/null +++ b/src/mod/sdk/autotools/autogen.sh @@ -0,0 +1,2 @@ +#!/bin/sh +autoreconf -i -f diff --git a/src/mod/sdk/autotools/configure.ac b/src/mod/sdk/autotools/configure.ac new file mode 100644 index 0000000000..d4f29f492b --- /dev/null +++ b/src/mod/sdk/autotools/configure.ac @@ -0,0 +1,252 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +# website url +m4_define([AC_PACKAGE_URL], [http://www.example.com/]) + +AC_PREREQ([2.61]) +AC_INIT([mod_example], [0.0.0], [contact@example.com]) +AC_CONFIG_SRCDIR([src/mod_example.c]) +AC_CONFIG_MACRO_DIR([m4]) + +AM_INIT_AUTOMAKE([foreign no-dist subdir-objects]) +AC_DISABLE_STATIC + +# disable libtool fortran and c++ checks +m4_defun([_LT_AC_LANG_F77_CONFIG], [:]) +m4_defun([_LT_AC_LANG_CXX_CONFIG], [:]) + +# >=automake-1.11 +m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) + +# Checks for programs. +AC_PROG_CC +AM_PROG_CC_C_O +AC_PROG_LIBTOOL + +# pkgconfig +AC_PATH_PROG([PKG_CONFIG], [pkg-config], ["no"]) +if test "x${PKG_CONFIG}" = "xno" +then + AC_MSG_ERROR([Cannot find pkg-config, make sure it is installed in your PATH]) +fi +PKG_PROG_PKG_CONFIG + +# Checks for cflags +AC_MSG_RESULT([${as_nl}<<>> Compiler vendor and features]) + +## +## Compiler vendor and flag checks +## +HAVE_VISIBILITY="no" +AC_ARG_ENABLE([visibility], + [AS_HELP_STRING([--disable-visibility], [Disable symbol visibility support (default: enabled, if available)])], + [case "${enableval}" in + yes) enable_visibility="yes" ;; + no) enable_visibility="no" ;; + *) AC_MSG_ERROR([Invalid value ${enableval} for parameter --disable-visibility]) ;; + esac], + [enable_visibility="yes"] +) + +AX_COMPILER_VENDOR + +case "${ax_cv_c_compiler_vendor}" in +gnu) + AC_MSG_CHECKING([whether the compiler supports -fvisibility=hidden]) + AS_IF([test "x${enable_visibility}" != "xno"], + [save_CFLAGS="${CFLAGS}" + CFLAGS="${CFLAGS} -fvisibility=hidden" + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [int foo __attribute__ ((visibility("default")));], + [;] + )], + + [AC_MSG_RESULT([yes]) + AC_DEFINE([HAVE_VISIBILITY],[1],[GCC visibility support]) + HAVE_VISIBILITY="yes"], + + [AC_MSG_RESULT([no]) + HAVE_VISIBILITY="no"] + ) + CFLAGS="${save_CFLAGS}"], + [AC_MSG_RESULT([disabled by user])] + ) + + AS_IF([test "x${HAVE_VISIBILITY}" != "xno"], + [save_CFLAGS="${CFLAGS}" + CFLAGS="${CFLAGS} -fvisibility-inlines-hidden" + AC_MSG_CHECKING([whether the compiler supports -fvisibility-inlines-hidden]) + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [;], [;] + )], + + [AC_MSG_RESULT([yes]) + HAVE_VISIBILITY_INLINES_HIDDEN="yes"], + + [AC_MSG_RESULT([no]) + HAVE_VISIBILITY_INLINES_HIDDEN="no"] + ) + CFLAGS="${save_CFLAGS}"], + [:] + ) + AC_DEFINE([COMPILER_GCC], [1], [Compiler is GCC]) + ;; +sun) + AC_MSG_CHECKING([whether the compiler supports -xldscope=hidden]) + AS_IF([test "x${enable_visibility}" != "xno"], + [save_CFLAGS="${CFLAGS}" + CFLAGS="${CFLAGS} -xldscope=hidden" + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [int foo __attribute__ ((visibility("default")));], + [;] + )], + + [AC_MSG_RESULT([yes]) + AC_DEFINE([HAVE_VISIBILITY],[1],[SUNCC visibility support]) + HAVE_VISIBILITY="yes"], + + [AC_MSG_RESULT([no]) + HAVE_VISIBILITY="no"] + ) + CFLAGS="${save_CFLAGS}"], + [AC_MSG_RESULT([disabled by user])] + ) + AC_DEFINE([COMPILER_SUNCC], [1], [Compiler is SunCC]) + ;; +*) + AC_MSG_WARN([No visibility checks for this compiler defined]) + ;; +esac + +AM_CONDITIONAL([COMPILER_GCC], [test "x${ax_cv_c_compiler_vendor}" = "xgnu"]) +AM_CONDITIONAL([COMPILER_SUNCC], [test "x${ax_cv_c_compiler_vendor}" = "xsun"]) + +AM_CONDITIONAL([HAVE_VISIBILITY], [test "x${HAVE_VISIBILITY}" = "xyes"]) +AM_CONDITIONAL([HAVE_VISIBILITY_INLINES_HIDDEN], [test "x${HAVE_VISIBILITY_INLINES_HIDDEN}" = "xyes"]) + +## +## pkgconfig based freeswitch detection code +## +AC_MSG_RESULT([${as_nl}<<>> FreeSWITCH environment]) + +PKG_CHECK_MODULES([freeswitch], [freeswitch], + [save_LIBS="${LIBS}" + save_CFLAGS="${CFLAGS}" + save_CPPFLAGS="${CPPFLAGS}" + + AC_MSG_CHECKING([FreeSWITCH version]) + + FREESWITCH_VERSION="`${PKG_CONFIG} --modversion freeswitch 2>/dev/null`" + AS_IF([test "x${FREESWITCH_VERSION}" = "x"], + [AC_MSG_ERROR([failed to get FreeSWITCH version])], + [AC_MSG_RESULT([$FREESWITCH_VERSION])] + ) + + AC_MSG_CHECKING([whether FreeSWITCH ${FREESWITCH_VERSION} is usable]) + CFLAGS="${freeswitch_CFLAGS}" + CPPFLAGS="${freeswitch_CPPFLAGS}" + LIBS="${freeswitch_LIBS}" + AC_TRY_LINK([#include ], + [switch_core_init(0, 0, NULL);], + [AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no]) + AC_MSG_ERROR([libfreeswitch is unusable, please check config.log for details])] + ) + LIBS="${save_LIBS}" + CFLAGS="${save_CFLAGS}" + CPPFLAGS="${save_CPPFLAGS}" + + # get locations, critical first + AC_MSG_CHECKING([for installation prefix]) + FREESWITCH_PREFIX_DIR="`${PKG_CONFIG} --variable=prefix freeswitch 2>/dev/null`" + AS_IF( + [test "x${FREESWITCH_PREFIX_DIR}" = "x"], [AC_MSG_ERROR([unable to get FreeSWITCH prefix directory])], + [test ! -e "${FREESWITCH_PREFIX_DIR}"], [AC_MSG_ERROR([FreeSWITCH prefix directory ${FREESWITCH_PREFIX_DIR} does not exist])] + ) + AC_MSG_RESULT([${FREESWITCH_PREFIX_DIR}]) + + AC_MSG_CHECKING([for modules directory]) + FREESWITCH_MODULES_DIR="`${PKG_CONFIG} --variable=modulesdir freeswitch 2>/dev/null`" + AS_IF( + [test "x${FREESWITCH_MODULES_DIR}" = "x"], [AC_MSG_ERROR([unable to get FreeSWITCH modules directory])], + [test ! -e "${FREESWITCH_MODULES_DIR}"], [AC_MSG_ERROR([FreeSWITCH modules directory ${FREESWITCH_MODULES_DIR} does not exist])] + ) + AC_MSG_RESULT([${FREESWITCH_MODULES_DIR}]) + + AC_MSG_CHECKING([for configuration directory]) + FREESWITCH_CONFIG_DIR="`${PKG_CONFIG} --variable=sysconfdir freeswitch 2>/dev/null`" + AS_IF( + [test "x${FREESWITCH_CONFIG_DIR}" = "x"], [AC_MSG_ERROR([unable to get FreeSWITCH configuration directory])], + [test ! -e "${FREESWITCH_CONFIG_DIR}"], [AC_MSG_ERROR([FreeSWITCH configuration directory ${FREESWITCH_CONFIG_DIR} does not exist])] + ) + AC_MSG_RESULT([${FREESWITCH_CONFIG_DIR}]) + + # non-critical paths + FREESWITCH_HTDOCS_DIR="`${PKG_CONFIG} --variable=htdocsdir freeswitch 2>/dev/null`" + + FREESWITCH_RUNTIME_DIR="`${PKG_CONFIG} --variable=runtimedir freeswitch 2>/dev/null`" + FREESWITCH_SCRIPTS_DIR="`${PKG_CONFIG} --variable=scriptsdir freeswitch 2>/dev/null`" + + # cflags, libs + AC_SUBST([FREESWITCH_CFLAGS], [${freeswitch_CFLAGS}]) + AC_SUBST([FREESWITCH_CPPFLAGS], [${freeswitch_CPPFLAGS}]) + AC_SUBST([FREESWITCH_LIBS], [${freeswitch_LIBS}]) + + # version + AC_SUBST([FREESWITCH_VERSION]) + + # locations + AC_SUBST([FREESWITCH_PREFIX_DIR]) + AC_SUBST([FREESWITCH_HTDOCS_DIR]) + AC_SUBST([FREESWITCH_CONFIG_DIR]) + AC_SUBST([FREESWITCH_MODULES_DIR]) + AC_SUBST([FREESWITCH_SCRIPTS_DIR]) + AC_SUBST([FREESWITCH_RUNTIME_DIR]) + ], + [AC_MSG_ERROR([FreeSWITCH not found])] +) + +## +## Add your other dependency checks here +## +AC_MSG_RESULT([${as_nl}<<>> Other dependencies]) + +# Checks for header files. + +# Checks for typedefs, structures, and compiler characteristics. + +# Checks for library functions. + +AC_MSG_RESULT([${as_nl}<<>> Create output files]) +AC_CONFIG_FILES([Makefile src/Makefile]) +AC_OUTPUT + +AC_MSG_RESULT([ +====================== Configuration Summary ===================== ++ Package + Name:...................... ${PACKAGE_NAME} + Version:................... ${PACKAGE_VERSION} + Bugreports:................ ${PACKAGE_BUGREPORT} + Website:................... ${PACKAGE_URL} + ++ Compiler + Vendor:.................... ${ax_cv_c_compiler_vendor} + Symbol visibility:......... ${HAVE_VISIBILITY} + ++ FreeSWITCH + Version:................... ${FREESWITCH_VERSION} + Prefix:.................... ${FREESWITCH_PREFIX_DIR} + Modules directory:......... ${FREESWITCH_MODULES_DIR} + Configuration directory:... ${FREESWITCH_CONFIG_DIR} + + Cflags/CPPflags/CXXflags:.. ${FREESWITCH_CFLAGS} ${FREESWITCH_CPPFLAGS} + LDflags/Libs:.............. ${FREESWITCH_LIBS} ${FREESWITCH_LDFLAGS} + ++ Other + N/A +================================================================== +]) diff --git a/src/mod/sdk/autotools/m4/ax_compiler_vendor.m4 b/src/mod/sdk/autotools/m4/ax_compiler_vendor.m4 new file mode 100644 index 0000000000..a24a58da0f --- /dev/null +++ b/src/mod/sdk/autotools/m4/ax_compiler_vendor.m4 @@ -0,0 +1,15 @@ +AC_DEFUN([AX_COMPILER_VENDOR], +[ +AC_CACHE_CHECK([for _AC_LANG compiler vendor], ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor, + [ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor=unknown + # note: don't check for gcc first since some other compilers define __GNUC__ + for ventest in intel:__ICC,__ECC,__INTEL_COMPILER ibm:__xlc__,__xlC__,__IBMC__,__IBMCPP__ gnu:__GNUC__ sun:__SUNPRO_C,__SUNPRO_CC hp:__HP_cc,__HP_aCC dec:__DECC,__DECCXX,__DECC_VER,__DECCXX_VER borland:__BORLANDC__,__TURBOC__ comeau:__COMO__ cray:_CRAYC kai:__KCC lcc:__LCC__ metrowerks:__MWERKS__ sgi:__sgi,sgi microsoft:_MSC_VER watcom:__WATCOMC__ portland:__PGI; do + vencpp="defined("`echo $ventest | cut -d: -f2 | sed 's/,/) || defined(/g'`")" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,[ +#if !($vencpp) + thisisanerror; +#endif +])], [ax_cv_]_AC_LANG_ABBREV[_compiler_vendor=`echo $ventest | cut -d: -f1`; break]) + done + ]) +]) diff --git a/src/mod/sdk/autotools/src/Makefile.am b/src/mod/sdk/autotools/src/Makefile.am new file mode 100644 index 0000000000..d2bad5bc80 --- /dev/null +++ b/src/mod/sdk/autotools/src/Makefile.am @@ -0,0 +1,66 @@ +moddir = @FREESWITCH_MODULES_DIR@ +sysconfdir = @FREESWITCH_CONFIG_DIR@ + +### +# Flags +# +AM_CFLAGS = +AM_CXXFLAGS= +AM_CPPFLAGS= -I. -I$(includedir) +AM_LDFLAGS = -L. -L$(libdir) -avoid-version -module -no-undefined -shared + +### +# GCC specific flags +# +if COMPILER_GCC +AM_CFLAGS += -Wall +# symbol visibility support +if HAVE_VISIBILITY +AM_CFLAGS += -fvisibility=hidden +AM_CXXFLAGS+= -fvisibility=hidden +AM_CPPFLAGS+= -DSWITCH_API_VISIBILITY=1 +endif +if HAVE_VISIBILITY_INLINES_HIDDEN +AM_CXXFLAGS += -fvisibility-inlines-hidden +endif +endif + +### +# SunCC specific flags +# +if COMPILER_SUNCC +AM_CFLAGS += +# symbol visibility support +if HAVE_VISIBILITY +AM_CFLAGS += -xldscope=hidden +AM_CXXFLAGS += -xldscope=hidden +AM_CPPFLAGS += -DSWITCH_API_VISIBILITY=1 +endif +endif + + +### +# add module(s) here, with suffix '.la' +# +mod_LTLIBRARIES = mod_example.la + +### +# mod_example +# +mod_example_la_SOURCES = mod_example.c +mod_example_la_CFLAGS = $(AM_CFLAGS) $(FREESWITCH_CFLAGS) +mod_example_la_CPPFLAGS= $(AM_CPPFLAGS) $(FREESWITCH_CPPFLAGS) +mod_example_la_LDFLAGS = $(AM_LDFLAGS) +mod_example_la_LIBADD = $(FREESWITCH_LIBS) + +# configuration file +#sysconf_DATA = example.conf.xml + +# +# install configuration +# +#install-sysconfDATA: +# $(INSTALL) -d $(DESTDIR)/$(sysconfdir) +# for x in $(sysconf_DATA); do \ +# test -e $(DESTDIR)$(sysconfdir)/$$x || $(INSTALL) -m644 $$x $(DESTDIR)$(sysconfdir)/$$x ; \ +# done diff --git a/src/mod/sdk/autotools/src/mod_example.c b/src/mod/sdk/autotools/src/mod_example.c new file mode 100644 index 0000000000..5e7755c752 --- /dev/null +++ b/src/mod/sdk/autotools/src/mod_example.c @@ -0,0 +1,84 @@ +/* + * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * Copyright (C) 2005/2006, Anthony Minessale II + * + * Version: MPL 1.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * + * The Initial Developer of the Original Code is + * Anthony Minessale II + * Portions created by the Initial Developer are Copyright (C) + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Anthony Minessale II + * Neal Horman + * + * + * mod_example.c -- Framework Demo Module + * + */ +#include + +/* +SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_example_shutdown); +SWITCH_MODULE_RUNTIME_FUNCTION(mod_example_runtime); +*/ + +SWITCH_MODULE_LOAD_FUNCTION(mod_example_load); +SWITCH_MODULE_DEFINITION(mod_example, mod_example_load, NULL, NULL); + +SWITCH_MODULE_LOAD_FUNCTION(mod_example_load) +{ + /* connect my internal structure to the blank pointer passed to me */ + *module_interface = switch_loadable_module_create_module_interface(pool, modname); + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Hello World!\n"); + + /* indicate that the module should continue to be loaded */ + return SWITCH_STATUS_SUCCESS; +} + +/* + Called when the system shuts down +SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_example_shutdown); +{ + return SWITCH_STATUS_SUCCESS; +} +*/ + +/* + If it exists, this is called in it's own thread when the module-load completes + If it returns anything but SWITCH_STATUS_TERM it will be called again automaticly +SWITCH_MODULE_RUNTIME_FUNCTION(mod_example_runtime); +{ + while(looping) + { + switch_yield(1000); + } + return SWITCH_STATUS_TERM; +} +*/ + +/* For Emacs: + * Local Variables: + * mode:c + * indent-tabs-mode:nil + * tab-width:4 + * c-basic-offset:4 + * End: + * For VIM: + * vim:set softtabstop=4 shiftwidth=4 tabstop=4 expandtab: + */ diff --git a/src/switch.c b/src/switch.c index c922d27ad0..33e7fb6336 100644 --- a/src/switch.c +++ b/src/switch.c @@ -404,7 +404,8 @@ int main(int argc, char *argv[]) #endif "\t-help -- this message\n" "\t-version -- print the version and exit\n" #ifdef HAVE_SETRLIMIT - "\t-waste -- allow memory waste\n" "\t-core -- dump cores\n" + "\t-waste -- allow memory waste\n" + "\t-core -- dump cores\n" #endif "\t-hp -- enable high priority settings\n" "\t-vg -- run under valgrind\n" @@ -552,6 +553,13 @@ int main(int argc, char *argv[]) } if (local_argv[x] && !strcmp(local_argv[x], "-waste")) { + fprintf(stderr, "WARNING: Wasting up to 8 megs of memory per thread.\n"); + sleep(2); + waste++; + known_opt++; + } + + if (local_argv[x] && !strcmp(local_argv[x], "-no-auto-stack")) { waste++; known_opt++; } @@ -771,8 +779,8 @@ int main(int argc, char *argv[]) char buf[1024] = ""; int i = 0; - fprintf(stderr, "Error: stacksize %d is too large: run ulimit -s %d or run %s -waste.\nauto-adjusting stack size for optimal performance...\n", - (int) (rlp.rlim_max / 1024), SWITCH_THREAD_STACKSIZE / 1024, local_argv[0]); + fprintf(stderr, "Error: stacksize %d is too large: run ulimit -s %d from your shell before starting the application.\nauto-adjusting stack size for optimal performance...\n", + (int) (rlp.rlim_max / 1024), SWITCH_THREAD_STACKSIZE / 1024); memset(&rlp, 0, sizeof(rlp)); rlp.rlim_cur = SWITCH_THREAD_STACKSIZE; diff --git a/src/switch_channel.c b/src/switch_channel.c index 9e3064b625..4341ea9214 100644 --- a/src/switch_channel.c +++ b/src/switch_channel.c @@ -1206,18 +1206,20 @@ SWITCH_DECLARE(void) switch_channel_wait_for_state(switch_channel_t *channel, sw } -SWITCH_DECLARE(void) switch_channel_wait_for_state_timeout(switch_channel_t *other_channel, switch_channel_state_t want_state, uint32_t timeout) +SWITCH_DECLARE(void) switch_channel_wait_for_state_timeout(switch_channel_t *channel, switch_channel_state_t want_state, uint32_t timeout) { switch_channel_state_t state; uint32_t count = 0; for (;;) { - state = switch_channel_get_running_state(other_channel); + state = switch_channel_get_running_state(channel); - if (state >= want_state) { + if ((channel->state == channel->running_state && channel->running_state == want_state) || channel->state >= CS_HANGUP) { break; } + switch_cond_next(); + if (++count >= timeout) { break; } @@ -2042,10 +2044,13 @@ SWITCH_DECLARE(void) switch_channel_event_set_extended_data(switch_channel_t *ch event->event_id == SWITCH_EVENT_REQUEST_PARAMS || event->event_id == SWITCH_EVENT_CHANNEL_DATA || event->event_id == SWITCH_EVENT_CHANNEL_EXECUTE_COMPLETE || + event->event_id == SWITCH_EVENT_CHANNEL_DESTROY || event->event_id == SWITCH_EVENT_SESSION_HEARTBEAT || event->event_id == SWITCH_EVENT_API || event->event_id == SWITCH_EVENT_RECORD_START || event->event_id == SWITCH_EVENT_RECORD_STOP || + event->event_id == SWITCH_EVENT_PLAYBACK_START || + event->event_id == SWITCH_EVENT_PLAYBACK_STOP || event->event_id == SWITCH_EVENT_CALL_UPDATE || event->event_id == SWITCH_EVENT_MEDIA_BUG_START || event->event_id == SWITCH_EVENT_MEDIA_BUG_STOP || diff --git a/src/switch_console.c b/src/switch_console.c index c5d601b9a2..a73bb58e89 100644 --- a/src/switch_console.c +++ b/src/switch_console.c @@ -252,7 +252,7 @@ SWITCH_DECLARE(char *) switch_console_expand_alias(char *cmd, char *arg) } - if (db->type == SCDB_TYPE_CORE_DB) { + if (switch_cache_db_get_type(db) == SCDB_TYPE_CORE_DB) { sql = switch_mprintf("select command from aliases where alias='%q'", cmd); } else { sql = switch_mprintf("select command from aliases where alias='%w'", cmd); @@ -268,7 +268,7 @@ SWITCH_DECLARE(char *) switch_console_expand_alias(char *cmd, char *arg) switch_safe_free(sql); if (!r) { - if (db->type == SCDB_TYPE_CORE_DB) { + if (switch_cache_db_get_type(db) == SCDB_TYPE_CORE_DB) { sql = switch_mprintf("select command from aliases where alias='%q %q'", cmd, arg); } else { sql = switch_mprintf("select command from aliases where alias='%w %w'", cmd, arg); @@ -794,7 +794,7 @@ SWITCH_DECLARE(unsigned char) switch_console_complete(const char *line, const ch stream.write_function(&stream, "select distinct a1 from complete where " "a1 not in (select name from interfaces where hostname='%s') %s ", switch_core_get_hostname(), argc ? "and" : ""); } else { - if (db->type == SCDB_TYPE_CORE_DB) { + if (switch_cache_db_get_type(db) == SCDB_TYPE_CORE_DB) { stream.write_function(&stream, "select distinct a%d,'%q','%q' from complete where ", h.words + 1, switch_str_nil(dup), switch_str_nil(lp)); } else { stream.write_function(&stream, "select distinct a%d,'%q','%w' from complete where ", h.words + 1, switch_str_nil(dup), switch_str_nil(lp)); @@ -803,7 +803,7 @@ SWITCH_DECLARE(unsigned char) switch_console_complete(const char *line, const ch for (x = 0; x < argc && x < 11; x++) { if (h.words + 1 > argc) { - if (db->type == SCDB_TYPE_CORE_DB) { + if (switch_cache_db_get_type(db) == SCDB_TYPE_CORE_DB) { stream.write_function(&stream, "(a%d like '::%%' or a%d = '' or a%d = '%q')%q", x + 1, x + 1, x + 1, switch_str_nil(argv[x]), x == argc - 1 ? "" : " and "); } else { @@ -811,7 +811,7 @@ SWITCH_DECLARE(unsigned char) switch_console_complete(const char *line, const ch x + 1, x + 1, x + 1, switch_str_nil(argv[x]), x == argc - 1 ? "" : " and "); } } else { - if (db->type == SCDB_TYPE_CORE_DB) { + if (switch_cache_db_get_type(db) == SCDB_TYPE_CORE_DB) { stream.write_function(&stream, "(a%d like '::%%' or a%d = '' or a%d like '%q%%')%q", x + 1, x + 1, x + 1, switch_str_nil(argv[x]), x == argc - 1 ? "" : " and "); } else { @@ -1765,6 +1765,11 @@ SWITCH_DECLARE(switch_status_t) switch_console_set_complete(const char *string) char *mydata = NULL, *argv[11] = { 0 }; int argc, x; switch_status_t status = SWITCH_STATUS_FALSE; + switch_core_flag_t cflags = switch_core_flags(); + + if (!(cflags & SCF_USE_SQL)) { + return SWITCH_STATUS_FALSE; + } if (string && (mydata = strdup(string))) { if ((argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) { @@ -1787,7 +1792,7 @@ SWITCH_DECLARE(switch_status_t) switch_console_set_complete(const char *string) if (argv[x + 1] && !strcasecmp(argv[x + 1], "_any_")) { mystream.write_function(&mystream, "%s", "'', "); } else { - if (db->type == SCDB_TYPE_CORE_DB) { + if (switch_cache_db_get_type(db) == SCDB_TYPE_CORE_DB) { mystream.write_function(&mystream, "'%q', ", switch_str_nil(argv[x + 1])); } else { mystream.write_function(&mystream, "'%w', ", switch_str_nil(argv[x + 1])); @@ -1803,7 +1808,7 @@ SWITCH_DECLARE(switch_status_t) switch_console_set_complete(const char *string) if (argv[x + 1] && !strcasecmp(argv[x + 1], "_any_")) { mystream.write_function(&mystream, "%s", "'', "); } else { - if (db->type == SCDB_TYPE_CORE_DB) { + if (switch_cache_db_get_type(db) == SCDB_TYPE_CORE_DB) { mystream.write_function(&mystream, "'%q', ", switch_str_nil(argv[x + 1])); } else { mystream.write_function(&mystream, "'%w', ", switch_str_nil(argv[x + 1])); @@ -1821,7 +1826,7 @@ SWITCH_DECLARE(switch_status_t) switch_console_set_complete(const char *string) } else { mystream.write_function(&mystream, "delete from complete where "); for (x = 0; x < argc - 1; x++) { - if (db->type == SCDB_TYPE_CORE_DB) { + if (switch_cache_db_get_type(db) == SCDB_TYPE_CORE_DB) { mystream.write_function(&mystream, "a%d = '%q'%q", x + 1, switch_str_nil(argv[x + 1]), x == argc - 2 ? "" : " and "); } else { mystream.write_function(&mystream, "a%d = '%w'%w", x + 1, switch_str_nil(argv[x + 1]), x == argc - 2 ? "" : " and "); @@ -1866,7 +1871,7 @@ SWITCH_DECLARE(switch_status_t) switch_console_set_alias(const char *string) sql = switch_mprintf("delete from aliases where alias='%q' and hostname='%q'", argv[1], switch_core_get_hostname()); switch_cache_db_persistant_execute(db, sql, 5); switch_safe_free(sql); - if (db->type == SCDB_TYPE_CORE_DB) { + if (switch_cache_db_get_type(db) == SCDB_TYPE_CORE_DB) { sql = switch_mprintf("insert into aliases (sticky, alias, command, hostname) values (1, '%q','%q','%q')", argv[1], argv[2], switch_core_get_hostname()); } else { @@ -1879,7 +1884,7 @@ SWITCH_DECLARE(switch_status_t) switch_console_set_alias(const char *string) sql = switch_mprintf("delete from aliases where alias='%q' and hostname='%q'", argv[1], switch_core_get_hostname()); switch_cache_db_persistant_execute(db, sql, 5); switch_safe_free(sql); - if (db->type == SCDB_TYPE_CORE_DB) { + if (switch_cache_db_get_type(db) == SCDB_TYPE_CORE_DB) { sql = switch_mprintf("insert into aliases (sticky, alias, command, hostname) values (0, '%q','%q','%q')", argv[1], argv[2], switch_core_get_hostname()); } else { diff --git a/src/switch_core.c b/src/switch_core.c index 5479229100..96e4b4ae27 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -98,10 +98,9 @@ static void check_ip(void) char old_ip6[256] = ""; int ok4 = 1, ok6 = 1; int mask = 0; - static char hostname[256] = ""; - gethostname(hostname, sizeof(hostname)); - switch_core_set_variable("hostname", hostname); + gethostname(runtime.hostname, sizeof(runtime.hostname)); + switch_core_set_variable("hostname", runtime.hostname); switch_find_local_ip(guess_ip4, sizeof(guess_ip4), &mask, AF_INET); switch_find_local_ip(guess_ip6, sizeof(guess_ip6), NULL, AF_INET6); @@ -1280,7 +1279,13 @@ SWITCH_DECLARE(switch_status_t) switch_core_init(switch_core_flag_t flags, switc /* one per customer */ return SWITCH_STATUS_SUCCESS; } + + memset(&runtime, 0, sizeof(runtime)); + gethostname(runtime.hostname, sizeof(runtime.hostname)); + runtime.max_db_handles = 50; + runtime.db_handle_timeout = 5000000;; + runtime.runlevel++; runtime.sql_buffer_len = 1024 * 32; runtime.max_sql_buffer_len = 1024 * 1024; @@ -1348,9 +1353,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_init(switch_core_flag_t flags, switc runtime.console = stdout; } - gethostname(runtime.hostname, sizeof(runtime.hostname)); switch_core_set_variable("hostname", runtime.hostname); - switch_find_local_ip(guess_ip, sizeof(guess_ip), &mask, AF_INET); switch_core_set_variable("local_ip_v4", guess_ip); in.s_addr = mask; @@ -1549,6 +1552,23 @@ static void switch_load_core_config(const char *file) if (tmp > -1 && tmp < 11) { switch_core_session_ctl(SCSC_DEBUG_LEVEL, &tmp); } + } else if (!strcasecmp(var, "max-db-handles")) { + long tmp = atol(val); + + if (tmp > 4 && tmp < 5001) { + runtime.max_db_handles = (uint32_t) tmp; + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "max-db-handles must be between 5 and 5000\n"); + } + } else if (!strcasecmp(var, "db-handle-timeout")) { + long tmp = atol(val); + + if (tmp > 0 && tmp < 5001) { + runtime.db_handle_timeout = (uint32_t) tmp * 1000000; + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "db-handle-timeout must be between 1 and 5000\n"); + } + } else if (!strcasecmp(var, "multiple-registrations")) { runtime.multiple_registrations = switch_true(val); } else if (!strcasecmp(var, "sql-buffer-len")) { diff --git a/src/switch_core_db.c b/src/switch_core_db.c index b3cd2ceff8..475bcfd649 100644 --- a/src/switch_core_db.c +++ b/src/switch_core_db.c @@ -182,9 +182,27 @@ SWITCH_DECLARE(switch_core_db_t *) switch_core_db_open_file(const char *filename { switch_core_db_t *db; char path[1024]; + int db_ret; db_pick_path(filename, path, sizeof(path)); - if (switch_core_db_open(path, &db)) { + if ((db_ret = switch_core_db_open(path, &db)) != SQLITE_OK) { + goto end; + } + if ((db_ret = switch_core_db_exec(db, "PRAGMA synchronous=OFF;", NULL, NULL, NULL) != SQLITE_OK)) { + goto end; + } + if ((db_ret = switch_core_db_exec(db, "PRAGMA count_changes=OFF;", NULL, NULL, NULL) != SQLITE_OK)) { + goto end; + } + if ((db_ret = switch_core_db_exec(db, "PRAGMA cache_size=8000;", NULL, NULL, NULL) != SQLITE_OK)) { + goto end; + } + if ((db_ret = switch_core_db_exec(db, "PRAGMA temp_store=MEMORY;", NULL, NULL, NULL) != SQLITE_OK)) { + goto end; + } + +end: + if (db_ret != SQLITE_OK) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQL ERR [%s]\n", switch_core_db_errmsg(db)); switch_core_db_close(db); db = NULL; diff --git a/src/switch_core_io.c b/src/switch_core_io.c index 4e1c7075b5..14cec65808 100644 --- a/src/switch_core_io.c +++ b/src/switch_core_io.c @@ -310,6 +310,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi } else { memset(session->raw_read_frame.data, 255, read_frame->codec->implementation->decoded_bytes_per_packet); } + + session->raw_read_frame.timestamp = 0; session->raw_read_frame.datalen = read_frame->codec->implementation->decoded_bytes_per_packet; session->raw_read_frame.samples = session->raw_read_frame.datalen / sizeof(int16_t); read_frame = &session->raw_read_frame; diff --git a/src/switch_core_memory.c b/src/switch_core_memory.c index dd87f8f4a2..7e6abf9c77 100644 --- a/src/switch_core_memory.c +++ b/src/switch_core_memory.c @@ -409,9 +409,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_perform_new_memory_pool(switch_memor SWITCH_DECLARE(switch_status_t) switch_core_perform_destroy_memory_pool(switch_memory_pool_t **pool, const char *file, const char *func, int line) { switch_assert(pool != NULL); - if (switch_core_memory_pool_get_data(*pool, "_in_thread")) { - switch_cache_db_detach(); - } + #ifdef DEBUG_ALLOC2 switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_CONSOLE, "Free Pool\n"); #endif diff --git a/src/switch_core_session.c b/src/switch_core_session.c index d2e28de523..2080c0b624 100644 --- a/src/switch_core_session.c +++ b/src/switch_core_session.c @@ -203,16 +203,12 @@ SWITCH_DECLARE(void) switch_core_session_hupall_matching_var(const char *var_nam for (hi = switch_hash_first(NULL, session_manager.session_table); hi; hi = switch_hash_next(hi)) { switch_hash_this(hi, NULL, NULL, &val); if (val) { - const char *this_val; session = (switch_core_session_t *) val; if (switch_core_session_read_lock(session) == SWITCH_STATUS_SUCCESS) { - if (switch_channel_up(session->channel) && - (this_val = switch_channel_get_variable(session->channel, var_name)) && (!strcmp(this_val, var_val))) { - np = switch_core_alloc(pool, sizeof(*np)); - np->str = switch_core_strdup(pool, session->uuid_str); - np->next = head; - head = np; - } + np = switch_core_alloc(pool, sizeof(*np)); + np->str = switch_core_strdup(pool, session->uuid_str); + np->next = head; + head = np; switch_core_session_rwunlock(session); } } @@ -221,7 +217,11 @@ SWITCH_DECLARE(void) switch_core_session_hupall_matching_var(const char *var_nam for(np = head; np; np = np->next) { if ((session = switch_core_session_locate(np->str))) { - switch_channel_hangup(session->channel, cause); + const char *this_val; + if (switch_channel_up(session->channel) && + (this_val = switch_channel_get_variable(session->channel, var_name)) && (!strcmp(this_val, var_val))) { + switch_channel_hangup(session->channel, cause); + } switch_core_session_rwunlock(session); } } @@ -1947,7 +1947,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_execute_application_get_flag do { sanity--; - ready = switch_channel_media_ready(session->channel); + ready = switch_channel_media_up(session->channel); switch_cond_next(); } while(!ready && sanity); diff --git a/src/switch_core_sqldb.c b/src/switch_core_sqldb.c index 1274213893..a4ed5ca83c 100644 --- a/src/switch_core_sqldb.c +++ b/src/switch_core_sqldb.c @@ -36,6 +36,21 @@ #include "private/switch_core_pvt.h" //*#define DEBUG_SQL 1 +struct switch_cache_db_handle { + char name[CACHE_DB_LEN]; + switch_cache_db_handle_type_t type; + switch_cache_db_native_handle_t native_handle; + time_t last_used; + switch_mutex_t *mutex; + switch_mutex_t *io_mutex; + switch_memory_pool_t *pool; + int32_t flags; + unsigned long hash; + char creator[CACHE_DB_LEN]; + char last_user[CACHE_DB_LEN]; + struct switch_cache_db_handle *next; +}; + static struct { switch_cache_db_handle_t *event_db; switch_queue_t *sql_queue[2]; @@ -48,12 +63,77 @@ static struct { switch_bool_t manage; switch_mutex_t *io_mutex; switch_mutex_t *dbh_mutex; - switch_hash_t *dbh_hash; + switch_cache_db_handle_t *handle_pool; switch_thread_cond_t *cond; switch_mutex_t *cond_mutex; + uint32_t total_handles; + uint32_t total_used_handles; } sql_manager; +static void add_handle(switch_cache_db_handle_t *dbh) +{ + switch_mutex_lock(sql_manager.dbh_mutex); + switch_set_flag(dbh, CDF_INUSE); + sql_manager.total_used_handles++; + dbh->next = sql_manager.handle_pool; + sql_manager.handle_pool = dbh; + sql_manager.total_handles++; + switch_mutex_lock(dbh->mutex); + switch_mutex_unlock(sql_manager.dbh_mutex); +} + +static void del_handle(switch_cache_db_handle_t *dbh) +{ + switch_cache_db_handle_t *dbhp, *last = NULL; + + switch_mutex_lock(sql_manager.dbh_mutex); + for (dbhp = sql_manager.handle_pool; dbhp; dbhp = dbhp->next) { + if (dbhp == dbh) { + if (last) { + last->next = dbhp->next; + } else { + sql_manager.handle_pool = dbhp->next; + } + sql_manager.total_handles--; + break; + } + + last = dbhp; + } + switch_mutex_unlock(sql_manager.dbh_mutex); +} + +static switch_cache_db_handle_t *get_handle(const char *db_str, const char *user_str) +{ + switch_ssize_t hlen = -1; + unsigned long hash = 0; + switch_cache_db_handle_t *dbhp, *r = NULL; + + + hash = switch_ci_hashfunc_default(db_str, &hlen); + + switch_mutex_lock(sql_manager.dbh_mutex); + for (dbhp = sql_manager.handle_pool; dbhp; dbhp = dbhp->next) { + if (dbhp->hash == hash && !switch_test_flag(dbhp, CDF_INUSE) && + !switch_test_flag(dbhp, CDF_PRUNE) && switch_mutex_trylock(dbhp->mutex) == SWITCH_STATUS_SUCCESS) { + r = dbhp; + + switch_set_flag(dbhp, CDF_INUSE); + sql_manager.total_used_handles++; + dbhp->hash = switch_ci_hashfunc_default(db_str, &hlen); + switch_set_string(dbhp->last_user, user_str); + + break; + } + } + switch_mutex_unlock(sql_manager.dbh_mutex); + + return r; + +} + + #define SWITCH_CORE_DB "core" /*! \brief Open the default system database @@ -93,62 +173,56 @@ SWITCH_DECLARE(switch_status_t) _switch_core_db_handle(switch_cache_db_handle_t #define SQL_CACHE_TIMEOUT 120 #define SQL_REG_TIMEOUT 15 + static void sql_close(time_t prune) { - switch_hash_index_t *hi; - const void *var; - void *val; switch_cache_db_handle_t *dbh = NULL; int locked = 0; - char *key; switch_mutex_lock(sql_manager.dbh_mutex); top: locked = 0; - for (hi = switch_hash_first(NULL, sql_manager.dbh_hash); hi; hi = switch_hash_next(hi)) { - switch_hash_this(hi, &var, NULL, &val); - key = (char *) var; + for (dbh = sql_manager.handle_pool; dbh; dbh = dbh->next) { + time_t diff = 0; - if ((dbh = (switch_cache_db_handle_t *) val)) { - time_t diff = 0; - - if (prune > 0 && prune > dbh->last_used) { - diff = (time_t) prune - dbh->last_used; - } - - if (prune > 0 && diff < SQL_CACHE_TIMEOUT && !switch_test_flag(dbh, CDF_PRUNE)) { - continue; - } - - if (switch_mutex_trylock(dbh->mutex) == SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10, "Dropping idle DB connection %s\n", key); - - switch (dbh->type) { - case SCDB_TYPE_ODBC: - { - switch_odbc_handle_destroy(&dbh->native_handle.odbc_dbh); - } - break; - case SCDB_TYPE_CORE_DB: - { - switch_core_db_close(dbh->native_handle.core_db_dbh); - dbh->native_handle.core_db_dbh = NULL; - } - break; - } - - switch_core_hash_delete(sql_manager.dbh_hash, key); - switch_mutex_unlock(dbh->mutex); - switch_core_destroy_memory_pool(&dbh->pool); - goto top; - - } else { - if (!prune) - locked++; - continue; - } + if (prune > 0 && prune > dbh->last_used) { + diff = (time_t) prune - dbh->last_used; } + + if (prune > 0 && (switch_test_flag(dbh, CDF_INUSE) || (diff < SQL_CACHE_TIMEOUT && !switch_test_flag(dbh, CDF_PRUNE)))) { + continue; + } + + if (switch_mutex_trylock(dbh->mutex) == SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10, "Dropping idle DB connection %s\n", dbh->name); + + switch (dbh->type) { + case SCDB_TYPE_ODBC: + { + switch_odbc_handle_destroy(&dbh->native_handle.odbc_dbh); + } + break; + case SCDB_TYPE_CORE_DB: + { + switch_core_db_close(dbh->native_handle.core_db_dbh); + dbh->native_handle.core_db_dbh = NULL; + } + break; + } + + del_handle(dbh); + switch_mutex_unlock(dbh->mutex); + switch_core_destroy_memory_pool(&dbh->pool); + goto top; + + } else { + if (!prune) { + locked++; + } + continue; + } + } if (locked) { @@ -159,135 +233,69 @@ static void sql_close(time_t prune) } +SWITCH_DECLARE(switch_cache_db_handle_type_t) switch_cache_db_get_type(switch_cache_db_handle_t *dbh) +{ + return dbh->type; +} + SWITCH_DECLARE(void) switch_cache_db_flush_handles(void) { sql_close(switch_epoch_time_now(NULL) + SQL_CACHE_TIMEOUT + 1); } - SWITCH_DECLARE(void) switch_cache_db_release_db_handle(switch_cache_db_handle_t **dbh) { if (dbh && *dbh) { - - switch ((*dbh)->type) { - case SCDB_TYPE_ODBC: - { - switch_clear_flag((*dbh), CDF_INUSE); - } - break; - default: - break; - } - + switch_mutex_lock(sql_manager.dbh_mutex); + (*dbh)->last_used = switch_epoch_time_now(NULL); + switch_clear_flag((*dbh), CDF_INUSE); switch_mutex_unlock((*dbh)->mutex); + sql_manager.total_used_handles--; *dbh = NULL; + switch_mutex_unlock(sql_manager.dbh_mutex); } } SWITCH_DECLARE(void) switch_cache_db_dismiss_db_handle(switch_cache_db_handle_t **dbh) { - if (dbh && *dbh) { - - if ((*dbh)->type == SCDB_TYPE_CORE_DB) { - switch_set_flag((*dbh), CDF_PRUNE); - } else { - switch_clear_flag((*dbh), CDF_INUSE); - } - - switch_mutex_unlock((*dbh)->mutex); - *dbh = NULL; - } + switch_cache_db_release_db_handle(dbh); } -SWITCH_DECLARE(void) switch_cache_db_destroy_db_handle(switch_cache_db_handle_t **dbh) -{ - if (dbh && *dbh) { - switch_mutex_lock(sql_manager.dbh_mutex); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10, "Deleting DB connection %s\n", (*dbh)->name); - - switch ((*dbh)->type) { - case SCDB_TYPE_ODBC: - { - switch_odbc_handle_destroy(&(*dbh)->native_handle.odbc_dbh); - } - break; - case SCDB_TYPE_CORE_DB: - { - switch_core_db_close((*dbh)->native_handle.core_db_dbh); - (*dbh)->native_handle.core_db_dbh = NULL; - } - break; - } - - - switch_core_hash_delete(sql_manager.dbh_hash, (*dbh)->name); - switch_mutex_unlock((*dbh)->mutex); - switch_core_destroy_memory_pool(&(*dbh)->pool); - *dbh = NULL; - switch_mutex_unlock(sql_manager.dbh_mutex); - } -} - -SWITCH_DECLARE(void) switch_cache_db_detach(void) -{ - char thread_str[CACHE_DB_LEN] = ""; - switch_hash_index_t *hi; - const void *var; - void *val; - char *key; - switch_cache_db_handle_t *dbh = NULL; - int prune = 0; - - snprintf(thread_str, sizeof(thread_str) - 1, "%lu", (unsigned long) (intptr_t) switch_thread_self()); - switch_mutex_lock(sql_manager.dbh_mutex); - - for (hi = switch_hash_first(NULL, sql_manager.dbh_hash); hi; hi = switch_hash_next(hi)) { - switch_hash_this(hi, &var, NULL, &val); - key = (char *) var; - if ((dbh = (switch_cache_db_handle_t *) val)) { - if (switch_mutex_trylock(dbh->mutex) == SWITCH_STATUS_SUCCESS) { - if (strstr(dbh->name, thread_str)) { - if (dbh->type == SCDB_TYPE_CORE_DB) { - switch_set_flag(dbh, CDF_PRUNE); - prune++; - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10, - "Detach cached DB handle %s [%s]\n", thread_str, switch_cache_db_type_name(dbh->type)); - switch_clear_flag(dbh, CDF_INUSE); - } - } - switch_mutex_unlock(dbh->mutex); - } - } - } - - switch_mutex_unlock(sql_manager.dbh_mutex); - - if (prune) { - sql_close(switch_epoch_time_now(NULL)); - } - -} - SWITCH_DECLARE(switch_status_t) _switch_cache_db_get_db_handle(switch_cache_db_handle_t **dbh, switch_cache_db_handle_type_t type, switch_cache_db_connection_options_t *connection_options, const char *file, const char *func, int line) { - switch_thread_id_t self = switch_thread_self(); - char thread_str[CACHE_DB_LEN] = ""; char db_str[CACHE_DB_LEN] = ""; char db_callsite_str[CACHE_DB_LEN] = ""; switch_cache_db_handle_t *new_dbh = NULL; switch_ssize_t hlen = -1; + int waiting = 0; + uint32_t yield_len = 100000, total_yield = 0; const char *db_name = NULL; const char *db_user = NULL; const char *db_pass = NULL; + while(runtime.max_db_handles && sql_manager.total_handles >= runtime.max_db_handles && sql_manager.total_used_handles >= sql_manager.total_handles) { + if (!waiting++) { + switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_WARNING, "Max handles %u exceeded, blocking....\n", + runtime.max_db_handles); + } + + switch_yield(yield_len); + total_yield += yield_len; + + if (runtime.db_handle_timeout && total_yield > runtime.db_handle_timeout) { + switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_ERROR, "Error connecting\n"); + *dbh = NULL; + return SWITCH_STATUS_FALSE; + } + } + switch (type) { case SCDB_TYPE_ODBC: { @@ -310,45 +318,13 @@ SWITCH_DECLARE(switch_status_t) _switch_cache_db_get_db_handle(switch_cache_db_h } snprintf(db_str, sizeof(db_str) - 1, "db=\"%s\";user=\"%s\";pass=\"%s\"", db_name, db_user, db_pass); - snprintf(thread_str, sizeof(thread_str) - 1, "%s;thread=\"%lu\"", db_str, (unsigned long) (intptr_t) self); snprintf(db_callsite_str, sizeof(db_callsite_str) - 1, "%s:%d", file, line); - switch_mutex_lock(sql_manager.dbh_mutex); - if ((new_dbh = switch_core_hash_find(sql_manager.dbh_hash, thread_str))) { - switch_set_string(new_dbh->last_user, db_callsite_str); + + if ((new_dbh = get_handle(db_str, db_callsite_str))) { switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_DEBUG10, - "Reuse Cached DB handle %s [%s]\n", thread_str, switch_cache_db_type_name(new_dbh->type)); + "Reuse Unused Cached DB handle %s [%s]\n", new_dbh->name, switch_cache_db_type_name(new_dbh->type)); } else { - switch_hash_index_t *hi; - const void *var; - void *val; - char *key; - unsigned long hash = 0; - - hash = switch_ci_hashfunc_default(db_str, &hlen); - - for (hi = switch_hash_first(NULL, sql_manager.dbh_hash); hi; hi = switch_hash_next(hi)) { - switch_hash_this(hi, &var, NULL, &val); - key = (char *) var; - - if ((new_dbh = (switch_cache_db_handle_t *) val)) { - if (hash == new_dbh->hash && !strncasecmp(new_dbh->name, db_str, strlen(db_str)) && - !switch_test_flag(new_dbh, CDF_INUSE) && !switch_test_flag(new_dbh, CDF_PRUNE) - && switch_mutex_trylock(new_dbh->mutex) == SWITCH_STATUS_SUCCESS) { - switch_set_flag(new_dbh, CDF_INUSE); - switch_set_string(new_dbh->name, thread_str); - new_dbh->hash = switch_ci_hashfunc_default(db_str, &hlen); - switch_set_string(new_dbh->last_user, db_callsite_str); - switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_DEBUG10, - "Reuse Unused Cached DB handle %s [%s]\n", thread_str, switch_cache_db_type_name(new_dbh->type)); - break; - } - } - new_dbh = NULL; - } - } - - if (!new_dbh) { switch_memory_pool_t *pool = NULL; switch_core_db_t *db = NULL; switch_odbc_handle_t *odbc_dbh = NULL; @@ -388,17 +364,15 @@ SWITCH_DECLARE(switch_status_t) _switch_cache_db_get_db_handle(switch_cache_db_h } switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_DEBUG10, - "Create Cached DB handle %s [%s]\n", thread_str, switch_cache_db_type_name(type)); + "Create Cached DB handle %s [%s] %s:%d\n", new_dbh->name, switch_cache_db_type_name(type), file, line); switch_core_new_memory_pool(&pool); new_dbh = switch_core_alloc(pool, sizeof(*new_dbh)); new_dbh->pool = pool; new_dbh->type = type; - switch_set_string(new_dbh->name, thread_str); - switch_set_flag(new_dbh, CDF_INUSE); + switch_set_string(new_dbh->name, db_str); new_dbh->hash = switch_ci_hashfunc_default(db_str, &hlen); - if (db) { new_dbh->native_handle.core_db_dbh = db; } else { @@ -407,9 +381,7 @@ SWITCH_DECLARE(switch_status_t) _switch_cache_db_get_db_handle(switch_cache_db_h switch_mutex_init(&new_dbh->mutex, SWITCH_MUTEX_UNNESTED, new_dbh->pool); switch_set_string(new_dbh->creator, db_callsite_str); - switch_mutex_lock(new_dbh->mutex); - - switch_core_hash_insert(sql_manager.dbh_hash, new_dbh->name, new_dbh); + add_handle(new_dbh); } end: @@ -417,9 +389,7 @@ SWITCH_DECLARE(switch_status_t) _switch_cache_db_get_db_handle(switch_cache_db_h if (new_dbh) { new_dbh->last_used = switch_epoch_time_now(NULL); } - - switch_mutex_unlock(sql_manager.dbh_mutex); - + *dbh = new_dbh; return *dbh ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE; @@ -431,13 +401,13 @@ static switch_status_t switch_cache_db_execute_sql_real(switch_cache_db_handle_t switch_status_t status = SWITCH_STATUS_FALSE; char *errmsg = NULL; char *tmp = NULL; + switch_mutex_t *io_mutex = dbh->io_mutex; + + if (io_mutex) switch_mutex_lock(io_mutex); - if (dbh->io_mutex) { - switch_mutex_lock(dbh->io_mutex); - } - - if (err) + if (err) { *err = NULL; + } switch (dbh->type) { case SCDB_TYPE_ODBC: @@ -469,9 +439,7 @@ static switch_status_t switch_cache_db_execute_sql_real(switch_cache_db_handle_t } - if (dbh->io_mutex) { - switch_mutex_unlock(dbh->io_mutex); - } + if (io_mutex) switch_mutex_unlock(io_mutex); return status; } @@ -556,10 +524,9 @@ static switch_status_t switch_cache_db_execute_sql_chunked(switch_cache_db_handl SWITCH_DECLARE(switch_status_t) switch_cache_db_execute_sql(switch_cache_db_handle_t *dbh, char *sql, char **err) { switch_status_t status = SWITCH_STATUS_FALSE; + switch_mutex_t *io_mutex = dbh->io_mutex; - if (dbh->io_mutex) { - switch_mutex_lock(dbh->io_mutex); - } + if (io_mutex) switch_mutex_lock(io_mutex); switch (dbh->type) { default: @@ -569,9 +536,7 @@ SWITCH_DECLARE(switch_status_t) switch_cache_db_execute_sql(switch_cache_db_hand break; } - if (dbh->io_mutex) { - switch_mutex_unlock(dbh->io_mutex); - } + if (io_mutex) switch_mutex_unlock(io_mutex); return status; @@ -599,11 +564,9 @@ SWITCH_DECLARE(int) switch_cache_db_affected_rows(switch_cache_db_handle_t *dbh) SWITCH_DECLARE(char *) switch_cache_db_execute_sql2str(switch_cache_db_handle_t *dbh, char *sql, char *str, size_t len, char **err) { switch_status_t status = SWITCH_STATUS_FALSE; + switch_mutex_t *io_mutex = dbh->io_mutex; - - if (dbh->io_mutex) { - switch_mutex_lock(dbh->io_mutex); - } + if (io_mutex) switch_mutex_lock(io_mutex); switch (dbh->type) { case SCDB_TYPE_CORE_DB: @@ -612,7 +575,7 @@ SWITCH_DECLARE(char *) switch_cache_db_execute_sql2str(switch_cache_db_handle_t if (switch_core_db_prepare(dbh->native_handle.core_db_dbh, sql, -1, &stmt, 0)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Statement Error [%s]!\n", sql); - return NULL; + goto end; } else { int running = 1; int colcount; @@ -652,9 +615,7 @@ SWITCH_DECLARE(char *) switch_cache_db_execute_sql2str(switch_cache_db_handle_t end: - if (dbh->io_mutex) { - switch_mutex_unlock(dbh->io_mutex); - } + if (io_mutex) switch_mutex_unlock(io_mutex); return status == SWITCH_STATUS_SUCCESS ? str : NULL; @@ -665,18 +626,20 @@ SWITCH_DECLARE(switch_status_t) switch_cache_db_persistant_execute(switch_cache_ char *errmsg = NULL; switch_status_t status = SWITCH_STATUS_FALSE; uint8_t forever = 0; + switch_mutex_t *io_mutex = dbh->io_mutex; if (!retries) { forever = 1; retries = 1000; } - if (dbh->io_mutex) { - switch_mutex_lock(dbh->io_mutex); - } - while (retries > 0) { + + if (io_mutex) switch_mutex_lock(io_mutex); switch_cache_db_execute_sql_real(dbh, sql, &errmsg); + if (io_mutex) switch_mutex_unlock(io_mutex); + + if (errmsg) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQL ERR [%s]\n", errmsg); switch_safe_free(errmsg); @@ -691,11 +654,7 @@ SWITCH_DECLARE(switch_status_t) switch_cache_db_persistant_execute(switch_cache_ break; } } - - if (dbh->io_mutex) { - switch_mutex_unlock(dbh->io_mutex); - } - + return status; } @@ -707,15 +666,14 @@ SWITCH_DECLARE(switch_status_t) switch_cache_db_persistant_execute_trans(switch_ uint8_t forever = 0; unsigned begin_retries = 100; uint8_t again = 0; + switch_mutex_t *io_mutex = dbh->io_mutex; if (!retries) { forever = 1; retries = 1000; } - if (dbh->io_mutex) { - switch_mutex_lock(dbh->io_mutex); - } + if (io_mutex) switch_mutex_lock(io_mutex); again: @@ -726,6 +684,7 @@ SWITCH_DECLARE(switch_status_t) switch_cache_db_persistant_execute_trans(switch_ switch_cache_db_execute_sql_real(dbh, "BEGIN", &errmsg); } else { switch_odbc_status_t result; + if ((result = switch_odbc_SQLSetAutoCommitAttr(dbh->native_handle.odbc_dbh, 0)) != SWITCH_ODBC_SUCCESS) { char tmp[100]; switch_snprintf(tmp, sizeof(tmp), "%s-%i", "Unable to Set AutoCommit Off", result); @@ -753,23 +712,23 @@ SWITCH_DECLARE(switch_status_t) switch_cache_db_persistant_execute_trans(switch_ goto again; } - + switch_yield(100000); if (begin_retries == 0) { goto done; } - } else { - break; + + continue; } + break; } while (retries > 0) { switch_cache_db_execute_sql(dbh, sql, &errmsg); - if (errmsg) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQL ERR [%s]\n", errmsg); free(errmsg); @@ -795,10 +754,7 @@ SWITCH_DECLARE(switch_status_t) switch_cache_db_persistant_execute_trans(switch_ switch_odbc_SQLSetAutoCommitAttr(dbh->native_handle.odbc_dbh, 1); } - if (dbh->io_mutex) { - switch_mutex_unlock(dbh->io_mutex); - } - + if (io_mutex) switch_mutex_unlock(io_mutex); return status; } @@ -808,14 +764,14 @@ SWITCH_DECLARE(switch_status_t) switch_cache_db_execute_sql_callback(switch_cach { switch_status_t status = SWITCH_STATUS_FALSE; char *errmsg = NULL; + switch_mutex_t *io_mutex = dbh->io_mutex; - if (err) + if (err) { *err = NULL; - - if (dbh->io_mutex) { - switch_mutex_lock(dbh->io_mutex); } + if (io_mutex) switch_mutex_lock(io_mutex); + switch (dbh->type) { case SCDB_TYPE_ODBC: @@ -829,16 +785,16 @@ SWITCH_DECLARE(switch_status_t) switch_cache_db_execute_sql_callback(switch_cach if (errmsg) { dbh->last_used = switch_epoch_time_now(NULL) - (SQL_CACHE_TIMEOUT * 2); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQL ERR: [%s] %s\n", sql, errmsg); + if (!strstr(errmsg, "query abort")) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQL ERR: [%s] %s\n", sql, errmsg); + } switch_core_db_free(errmsg); } } break; } - if (dbh->io_mutex) { - switch_mutex_unlock(dbh->io_mutex); - } + if (io_mutex) switch_mutex_unlock(io_mutex); return status; } @@ -848,15 +804,14 @@ SWITCH_DECLARE(switch_bool_t) switch_cache_db_test_reactive(switch_cache_db_hand { char *errmsg; switch_bool_t r = SWITCH_TRUE; + switch_mutex_t *io_mutex = dbh->io_mutex; if (!switch_test_flag((&runtime), SCF_AUTO_SCHEMAS)) { switch_cache_db_execute_sql(dbh, (char *)test_sql, NULL); return SWITCH_TRUE; } - if (dbh->io_mutex) { - switch_mutex_lock(dbh->io_mutex); - } + if (io_mutex) switch_mutex_lock(io_mutex); switch (dbh->type) { case SCDB_TYPE_ODBC: @@ -901,9 +856,7 @@ SWITCH_DECLARE(switch_bool_t) switch_cache_db_test_reactive(switch_cache_db_hand } - if (dbh->io_mutex) { - switch_mutex_unlock(dbh->io_mutex); - } + if (io_mutex) switch_mutex_unlock(io_mutex); return r; } @@ -922,7 +875,7 @@ static void *SWITCH_THREAD_FUNC switch_core_sql_db_thread(switch_thread_t *threa sec = 0; } - if (++reg_sec == SQL_REG_TIMEOUT) { + if (switch_test_flag((&runtime), SCF_USE_SQL) && ++reg_sec == SQL_REG_TIMEOUT) { switch_core_expire_registration(0); reg_sec = 0; } @@ -1648,6 +1601,10 @@ SWITCH_DECLARE(switch_status_t) switch_core_add_registration(const char *user, c switch_cache_db_handle_t *dbh; char *sql; + if (!switch_test_flag((&runtime), SCF_USE_SQL)) { + return SWITCH_STATUS_FALSE; + } + if (switch_core_db_handle(&dbh) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB!\n"); return SWITCH_STATUS_FALSE; @@ -1691,12 +1648,20 @@ SWITCH_DECLARE(switch_status_t) switch_core_del_registration(const char *user, c switch_cache_db_handle_t *dbh; char *sql; + if (!switch_test_flag((&runtime), SCF_USE_SQL)) { + return SWITCH_STATUS_FALSE; + } + if (switch_core_db_handle(&dbh) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB!\n"); return SWITCH_STATUS_FALSE; } - sql = switch_mprintf("delete from registrations where reg_user='%q' and realm='%q' and hostname='%q'", user, realm, switch_core_get_hostname()); + if (!zstr(token) && runtime.multiple_registrations) { + sql = switch_mprintf("delete from registrations where reg_user='%q' and realm='%q' and hostname='%q' and token='%q'", user, realm, switch_core_get_hostname(), token); + } else { + sql = switch_mprintf("delete from registrations where reg_user='%q' and realm='%q' and hostname='%q'", user, realm, switch_core_get_hostname()); + } switch_cache_db_execute_sql(dbh, sql, NULL); switch_cache_db_release_db_handle(&dbh); @@ -1713,6 +1678,10 @@ SWITCH_DECLARE(switch_status_t) switch_core_expire_registration(int force) char *sql; switch_time_t now; + if (!switch_test_flag((&runtime), SCF_USE_SQL)) { + return SWITCH_STATUS_FALSE; + } + if (switch_core_db_handle(&dbh) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB!\n"); return SWITCH_STATUS_FALSE; @@ -1723,7 +1692,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_expire_registration(int force) if (force) { sql = switch_mprintf("delete from registrations where hostname='%q'", switch_core_get_hostname()); } else { - sql = switch_mprintf("delete from registrations where expires <= %ld and hostname='%q'", now, switch_core_get_hostname()); + sql = switch_mprintf("delete from registrations where expires > 0 and expires <= %ld and hostname='%q'", now, switch_core_get_hostname()); } switch_cache_db_execute_sql(dbh, sql, NULL); @@ -1750,8 +1719,6 @@ switch_status_t switch_core_sqldb_start(switch_memory_pool_t *pool, switch_bool_ switch_thread_cond_create(&sql_manager.cond, sql_manager.memory_pool); - switch_core_hash_init(&sql_manager.dbh_hash, sql_manager.memory_pool); - top: if (!sql_manager.manage) goto skip; @@ -1917,7 +1884,7 @@ void switch_core_sqldb_stop(void) if (sql_manager.manage) { switch_queue_push(sql_manager.sql_queue[0], NULL); switch_queue_push(sql_manager.sql_queue[1], NULL); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Waiting for unfinished SQL transactions\n"); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10, "Waiting for unfinished SQL transactions\n"); wake_thread(0); } @@ -1933,61 +1900,58 @@ void switch_core_sqldb_stop(void) switch_cache_db_flush_handles(); sql_close(0); - - switch_core_hash_destroy(&sql_manager.dbh_hash); - } SWITCH_DECLARE(void) switch_cache_db_status(switch_stream_handle_t *stream) { /* return some status info suitable for the cli */ - switch_hash_index_t *hi; switch_cache_db_handle_t *dbh = NULL; - void *val; - const void *var; - char *key; switch_bool_t locked = SWITCH_FALSE; time_t now = switch_epoch_time_now(NULL); char cleankey_str[CACHE_DB_LEN]; char *pos1 = NULL; char *pos2 = NULL; + int count = 0, used = 0; switch_mutex_lock(sql_manager.dbh_mutex); - for (hi = switch_hash_first(NULL, sql_manager.dbh_hash); hi; hi = switch_hash_next(hi)) { - switch_hash_this(hi, &var, NULL, &val); - key = (char *) var; + for (dbh = sql_manager.handle_pool; dbh; dbh = dbh->next) { + char *needle = "pass=\""; + time_t diff = 0; - if ((dbh = (switch_cache_db_handle_t *) val)) { - char *needle = "pass=\""; - time_t diff = 0; + diff = now - dbh->last_used; - diff = now - dbh->last_used; - - if (switch_mutex_trylock(dbh->mutex) == SWITCH_STATUS_SUCCESS) { - switch_mutex_unlock(dbh->mutex); - locked = SWITCH_FALSE; - } else { - locked = SWITCH_TRUE; - } - - /* sanitize password */ - memset(cleankey_str, 0, sizeof(cleankey_str)); - pos1 = strstr(key, needle) + strlen(needle); - pos2 = strstr(pos1, "\""); - strncpy(cleankey_str, key, pos1 - key); - strcpy(&cleankey_str[pos1 - key], pos2); - - - stream->write_function(stream, "%s\n\tType: %s\n\tLast used: %d\n\tFlags: %s, %s\n" - "\tCreator: %s\n\tLast User: %s\n", - cleankey_str, - switch_cache_db_type_name(dbh->type), - diff, - locked ? "Locked" : "Unlocked", - switch_test_flag(dbh, CDF_INUSE) ? "Attached" : "Detached", dbh->creator, dbh->last_user); + if (switch_mutex_trylock(dbh->mutex) == SWITCH_STATUS_SUCCESS) { + switch_mutex_unlock(dbh->mutex); + locked = SWITCH_FALSE; + } else { + locked = SWITCH_TRUE; } + + /* sanitize password */ + memset(cleankey_str, 0, sizeof(cleankey_str)); + pos1 = strstr(dbh->name, needle) + strlen(needle); + pos2 = strstr(pos1, "\""); + strncpy(cleankey_str, dbh->name, pos1 - dbh->name); + strcpy(&cleankey_str[pos1 - dbh->name], pos2); + + count++; + + if (switch_test_flag(dbh, CDF_INUSE)) { + used++; + } + + stream->write_function(stream, "%s\n\tType: %s\n\tLast used: %d\n\tFlags: %s, %s\n" + "\tCreator: %s\n\tLast User: %s\n", + cleankey_str, + switch_cache_db_type_name(dbh->type), + diff, + locked ? "Locked" : "Unlocked", + switch_test_flag(dbh, CDF_INUSE) ? "Attached" : "Detached", dbh->creator, dbh->last_user); } + + stream->write_function(stream, "%d total. %d in use.\n", count, used); + switch_mutex_unlock(sql_manager.dbh_mutex); } diff --git a/src/switch_core_state_machine.c b/src/switch_core_state_machine.c index 276acb8585..e2d50704b5 100644 --- a/src/switch_core_state_machine.c +++ b/src/switch_core_state_machine.c @@ -468,7 +468,7 @@ static void api_hook(switch_core_session_t *session, const char *hook_var, int u { if (!zstr(hook_var)) { switch_stream_handle_t stream = { 0 }; - char *cmd = switch_core_session_strdup(session, hook_var); + char *cmd = strdup(hook_var); char *arg = NULL; char *expanded = NULL; @@ -485,7 +485,7 @@ static void api_hook(switch_core_session_t *session, const char *hook_var, int u switch_channel_get_variables(session->channel, &stream.param_event); switch_channel_event_set_data(session->channel, stream.param_event); - expanded = switch_channel_expand_variables(session->channel, arg); + expanded = switch_event_expand_headers(stream.param_event, arg); switch_api_execute(cmd, expanded, use_session ? session : NULL, &stream); @@ -496,6 +496,9 @@ static void api_hook(switch_core_session_t *session, const char *hook_var, int u if (expanded != arg) { switch_safe_free(expanded); } + + switch_safe_free(cmd); + switch_safe_free(stream.data); } } diff --git a/src/switch_cpp.cpp b/src/switch_cpp.cpp index c62946b760..3ffc6a3a9d 100644 --- a/src/switch_cpp.cpp +++ b/src/switch_cpp.cpp @@ -501,8 +501,14 @@ SWITCH_DECLARE_CONSTRUCTOR CoreSession::CoreSession() SWITCH_DECLARE_CONSTRUCTOR CoreSession::CoreSession(char *nuuid, CoreSession *a_leg) { + switch_channel_t *other_channel = NULL; + init_vars(); + if (a_leg && a_leg->session) { + other_channel = switch_core_session_get_channel(a_leg->session); + } + if (!strchr(nuuid, '/') && (session = switch_core_session_locate(nuuid))) { uuid = strdup(nuuid); channel = switch_core_session_get_channel(session); @@ -516,6 +522,7 @@ SWITCH_DECLARE_CONSTRUCTOR CoreSession::CoreSession(char *nuuid, CoreSession *a_ switch_set_flag(this, S_HUP); uuid = strdup(switch_core_session_get_uuid(session)); switch_channel_set_state(switch_core_session_get_channel(session), CS_SOFT_EXECUTE); + switch_channel_wait_for_state(channel, other_channel, CS_SOFT_EXECUTE); } } } diff --git a/src/switch_event.c b/src/switch_event.c index b626d5b846..56ee9e9a9c 100644 --- a/src/switch_event.c +++ b/src/switch_event.c @@ -189,6 +189,8 @@ static char *EVENT_NAMES[] = { "NAT", "RECORD_START", "RECORD_STOP", + "PLAYBACK_START", + "PLAYBACK_STOP", "CALL_UPDATE", "FAILURE", "SOCKET_DATA", diff --git a/src/switch_ivr.c b/src/switch_ivr.c index a40da1b077..5a082763b2 100644 --- a/src/switch_ivr.c +++ b/src/switch_ivr.c @@ -2289,7 +2289,7 @@ SWITCH_DECLARE(void) switch_ivr_delay_echo(switch_core_session_t *session, uint3 qlen = delay_ms / (interval); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Setting delay to %dms (%d frames)\n", delay_ms, qlen); - jb = stfu_n_init(qlen, qlen, read_impl.samples_per_packet, read_impl.samples_per_second); + jb = stfu_n_init(qlen, qlen, read_impl.samples_per_packet, read_impl.samples_per_second, 0); write_frame.codec = switch_core_session_get_read_codec(session); diff --git a/src/switch_ivr_async.c b/src/switch_ivr_async.c index be360138c2..3afbfb6397 100644 --- a/src/switch_ivr_async.c +++ b/src/switch_ivr_async.c @@ -3216,8 +3216,10 @@ static switch_status_t speech_on_dtmf(switch_core_session_t *session, const swit switch_status_t status = SWITCH_STATUS_SUCCESS; switch_asr_flag_t flags = SWITCH_ASR_FLAG_NONE; - if (switch_core_asr_feed_dtmf(sth->ah, dtmf, &flags) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error Feeding DTMF\n"); + if (sth) { + if (switch_core_asr_feed_dtmf(sth->ah, dtmf, &flags) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error Feeding DTMF\n"); + } } return status; @@ -3231,6 +3233,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_stop_detect_speech(switch_core_sessio switch_assert(channel != NULL); if ((sth = switch_channel_get_private(channel, SWITCH_SPEECH_KEY))) { switch_channel_set_private(channel, SWITCH_SPEECH_KEY, NULL); + switch_core_event_hook_remove_recv_dtmf(session, speech_on_dtmf); switch_core_media_bug_remove(session, &sth->bug); return SWITCH_STATUS_SUCCESS; } @@ -3265,14 +3268,13 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_resume_detect_speech(switch_core_sess SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech_load_grammar(switch_core_session_t *session, char *grammar, char *name) { switch_channel_t *channel = switch_core_session_get_channel(session); - switch_asr_flag_t flags = SWITCH_ASR_FLAG_NONE; struct speech_thread_handle *sth = switch_channel_get_private(channel, SWITCH_SPEECH_KEY); switch_status_t status; if (sth) { if ((status = switch_core_asr_load_grammar(sth->ah, grammar, name)) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Error loading Grammar\n"); - switch_core_asr_close(sth->ah, &flags); + switch_ivr_stop_detect_speech(session); } return status; } @@ -3307,14 +3309,13 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech_start_input_timers(swit SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech_unload_grammar(switch_core_session_t *session, const char *name) { switch_channel_t *channel = switch_core_session_get_channel(session); - switch_asr_flag_t flags = SWITCH_ASR_FLAG_NONE; struct speech_thread_handle *sth = switch_channel_get_private(channel, SWITCH_SPEECH_KEY); switch_status_t status; if (sth) { if ((status = switch_core_asr_unload_grammar(sth->ah, name)) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Error unloading Grammar\n"); - switch_core_asr_close(sth->ah, &flags); + switch_ivr_stop_detect_speech(session); } return status; } @@ -3324,14 +3325,13 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech_unload_grammar(switch_c SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech_enable_grammar(switch_core_session_t *session, const char *name) { switch_channel_t *channel = switch_core_session_get_channel(session); - switch_asr_flag_t flags = SWITCH_ASR_FLAG_NONE; struct speech_thread_handle *sth = switch_channel_get_private(channel, SWITCH_SPEECH_KEY); switch_status_t status; if (sth) { if ((status = switch_core_asr_enable_grammar(sth->ah, name)) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Error enabling Grammar\n"); - switch_core_asr_close(sth->ah, &flags); + switch_ivr_stop_detect_speech(session); } return status; } @@ -3341,14 +3341,13 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech_enable_grammar(switch_c SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech_disable_grammar(switch_core_session_t *session, const char *name) { switch_channel_t *channel = switch_core_session_get_channel(session); - switch_asr_flag_t flags = SWITCH_ASR_FLAG_NONE; struct speech_thread_handle *sth = switch_channel_get_private(channel, SWITCH_SPEECH_KEY); switch_status_t status; if (sth) { if ((status = switch_core_asr_disable_grammar(sth->ah, name)) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Error disabling Grammar\n"); - switch_core_asr_close(sth->ah, &flags); + switch_ivr_stop_detect_speech(session); } return status; } @@ -3358,14 +3357,13 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech_disable_grammar(switch_ SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech_disable_all_grammars(switch_core_session_t *session) { switch_channel_t *channel = switch_core_session_get_channel(session); - switch_asr_flag_t flags = SWITCH_ASR_FLAG_NONE; struct speech_thread_handle *sth = switch_channel_get_private(channel, SWITCH_SPEECH_KEY); switch_status_t status; if (sth) { if ((status = switch_core_asr_disable_all_grammars(sth->ah)) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Error disabling all Grammars\n"); - switch_core_asr_close(sth->ah, &flags); + switch_ivr_stop_detect_speech(session); } return status; } @@ -3397,7 +3395,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech(switch_core_session_t * if (sth) { if (switch_core_asr_load_grammar(sth->ah, grammar, name) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Error loading Grammar\n"); - switch_core_asr_close(sth->ah, &flags); + switch_ivr_stop_detect_speech(session); return SWITCH_STATUS_FALSE; } diff --git a/src/switch_ivr_bridge.c b/src/switch_ivr_bridge.c index f130625a75..88c72bf1b8 100644 --- a/src/switch_ivr_bridge.c +++ b/src/switch_ivr_bridge.c @@ -1398,10 +1398,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_uuid_bridge(const char *originator_uu return SWITCH_STATUS_FALSE; } - //if (!switch_channel_test_flag(originator_channel, CF_ANSWERED)) { - if (!switch_channel_media_ready(originator_channel)) { - if (switch_channel_media_ready(originatee_channel)) { - //if (switch_channel_test_flag(originatee_channel, CF_ANSWERED)) { + if (!switch_channel_media_up(originator_channel)) { + if (switch_channel_media_up(originatee_channel)) { swap_session = originator_session; originator_session = originatee_session; originatee_session = swap_session; diff --git a/src/switch_ivr_play_say.c b/src/switch_ivr_play_say.c index dc263e9be5..98dfd0f71e 100644 --- a/src/switch_ivr_play_say.c +++ b/src/switch_ivr_play_say.c @@ -746,12 +746,6 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se } - if (switch_event_create(&event, SWITCH_EVENT_RECORD_STOP) == SWITCH_STATUS_SUCCESS) { - switch_channel_event_set_data(channel, event); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Record-File-Path", file); - switch_event_fire(&event); - } - if (fill_cng || waste_resources) { switch_core_codec_destroy(&write_codec); } @@ -766,6 +760,12 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se switch_channel_set_variable_printf(channel, "record_samples", "%d", fh->samples_out); + if (switch_event_create(&event, SWITCH_EVENT_RECORD_STOP) == SWITCH_STATUS_SUCCESS) { + switch_channel_event_set_data(channel, event); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Record-File-Path", file); + switch_event_fire(&event); + } + switch_core_session_reset(session, SWITCH_TRUE, SWITCH_TRUE); return status; } @@ -951,6 +951,38 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_release_file_handle(switch_core_sessi #define FILE_BLOCKSIZE 1024 * 8 #define FILE_BUFSIZE 1024 * 64 +static void add_playback_vars_to_event(switch_core_session_t *session, switch_event_t *event, char *vars) +{ + char *tmp; + + if (!session || !event || !vars) + return; + + if ((tmp = switch_core_session_strdup(session, vars))) { + char *argv[128] = { 0 }; + int argc, i; + + if (!(argc = switch_separate_string(tmp, ',', argv, (sizeof(argv) / sizeof(argv[0]))))) + return; + + for (i = 0; i < argc; i++) { + char *var, *val; + + if ((var = strchr(argv[i], '='))) { + *var = '\0'; + val = var+1; + var = argv[i]; + + if (var && *var && val && *val) { + if ((var = switch_core_session_sprintf(session, "playback_variable_%s", var))) { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, var, val); + } + } + } + } + } +} + SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *session, switch_file_handle_t *fh, const char *file, switch_input_args_t *args) { switch_channel_t *channel = switch_core_session_get_channel(session); @@ -990,6 +1022,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess int timeout_samples = 0; const char *var; int more_data = 0; + char *playback_vars, *tmp; + switch_event_t *event; if (switch_channel_pre_answer(channel) != SWITCH_STATUS_SUCCESS) { return SWITCH_STATUS_FALSE; @@ -1138,6 +1172,19 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess } } + /* Try to parse extra parameters for this playback (parameters within {} at the end of the filename */ + playback_vars = NULL; + if ((tmp = strchr(file, '{'))) { + char *tfile, *e; + + if ((tfile = switch_core_session_strdup(session, tmp))) { + if ((e = switch_find_end_paren(tfile, '{', '}')) && *(e + 1) == '\0') { + *tmp = '\0'; + *e = '\0'; + playback_vars = tfile+1; + } + } + } if (!fh) { fh = &lfh; @@ -1293,6 +1340,13 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess ilen = samples; + if (switch_event_create(&event, SWITCH_EVENT_PLAYBACK_START) == SWITCH_STATUS_SUCCESS) { + switch_channel_event_set_data(channel, event); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Playback-File-Path", file); + add_playback_vars_to_event(session, event, playback_vars); + switch_event_fire(&event); + } + for (;;) { int do_speed = 1; int last_speed = -1; @@ -1586,6 +1640,18 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess } switch_channel_set_variable_printf(channel, "playback_samples", "%d", fh->samples_in); + if (switch_event_create(&event, SWITCH_EVENT_PLAYBACK_STOP) == SWITCH_STATUS_SUCCESS) { + switch_channel_event_set_data(channel, event); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Playback-File-Path", file); + if (status == SWITCH_STATUS_BREAK) { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Playback-Status", "break"); + } else { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Playback-Status", "done"); + } + add_playback_vars_to_event(session, event, playback_vars); + switch_event_fire(&event); + } + switch_core_session_io_write_lock(session); switch_channel_set_private(channel, "__fh", NULL); switch_core_session_io_rwunlock(session); diff --git a/src/switch_nat.c b/src/switch_nat.c index 85b0247d6d..d9110efe18 100644 --- a/src/switch_nat.c +++ b/src/switch_nat.c @@ -325,9 +325,9 @@ static void *SWITCH_THREAD_FUNC switch_nat_multicast_runtime(switch_thread_t * t do_repub = SWITCH_TRUE; switch_event_create(&event, SWITCH_EVENT_TRAP); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "condition", "network-address-change"); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "network-address-previous-v4", nat_globals.pub_addr); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "network-address-change-v4", newip); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "condition", "network-external-address-change"); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "network-external-address-previous-v4", nat_globals.pub_addr); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "network-external-address-change-v4", newip); switch_event_fire(&event); switch_set_string(nat_globals.pub_addr, newip); diff --git a/src/switch_resample.c b/src/switch_resample.c index 10c633c01a..9c7f9b95d2 100644 --- a/src/switch_resample.c +++ b/src/switch_resample.c @@ -269,25 +269,29 @@ SWITCH_DECLARE(void) switch_mux_channels(int16_t *data, switch_size_t samples, u } -SWITCH_DECLARE(void) switch_change_sln_volume(int16_t *data, uint32_t samples, int32_t vol) +SWITCH_DECLARE(void) switch_change_sln_volume_granular(int16_t *data, uint32_t samples, int32_t vol) { double newrate = 0; - int div = 0; + double pos[12] = {1.25, 1.50, 1.75, 2.0, 2.25, 2.50, 2.75, 3.0, 3.25, 3.50, 3.75, 4.0}; + double neg[12] = {.917, .834, .751, .668, .585, .502, .419, .336, .253, .017, .087, .004}; + double *chart; + uint32_t i; - switch_normalize_volume(vol); + if (vol == 0) return; + + switch_normalize_volume_granular(vol); if (vol > 0) { - vol++; - } else if (vol < 0) { - vol--; + chart = pos; + } else { + chart = neg; } + + i = abs(vol) - 1; + + switch_assert(i < 12); - newrate = vol * 1.3; - - if (vol < 0) { - newrate *= -1; - div++; - } + newrate = chart[i]; if (newrate) { int32_t tmp; @@ -295,7 +299,44 @@ SWITCH_DECLARE(void) switch_change_sln_volume(int16_t *data, uint32_t samples, i int16_t *fp = data; for (x = 0; x < samples; x++) { - tmp = (int32_t) (div ? fp[x] / newrate : fp[x] * newrate); + tmp = (int32_t) (fp[x] * newrate); + switch_normalize_to_16bit(tmp); + fp[x] = (int16_t) tmp; + } + } +} + +SWITCH_DECLARE(void) switch_change_sln_volume(int16_t *data, uint32_t samples, int32_t vol) +{ + double newrate = 0; + double pos[4] = {1.3, 2.3, 3.3, 4.3}; + double neg[4] = {.80, .60, .40, .20}; + double *chart; + uint32_t i; + + if (vol == 0) return; + + switch_normalize_volume(vol); + + if (vol > 0) { + chart = pos; + } else { + chart = neg; + } + + i = abs(vol) - 1; + + switch_assert(i < 4); + + newrate = chart[i]; + + if (newrate) { + int32_t tmp; + uint32_t x; + int16_t *fp = data; + + for (x = 0; x < samples; x++) { + tmp = (int32_t) (fp[x] * newrate); switch_normalize_to_16bit(tmp); fp[x] = (int16_t) tmp; } diff --git a/src/switch_rtp.c b/src/switch_rtp.c index d0c22ce585..f5a7022928 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -235,7 +235,6 @@ struct switch_rtp { uint32_t sync_packets; int rtcp_interval; switch_bool_t rtcp_fresh_frame; - uint8_t checked_jb; #ifdef ENABLE_ZRTP zrtp_session_t *zrtp_session; zrtp_profile_t *zrtp_profile; @@ -1830,7 +1829,7 @@ static void jb_callback(stfu_instance_t *i, void *udata) stfu_n_report(i, &r); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG8, "%s JB REPORT:\nlen: %u\nin: %u\nclean: %u\ngood: %u\nbad: %u\n", switch_core_session_get_name(session), r.qlen, @@ -1910,7 +1909,8 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_activate_jitter_buffer(switch_rtp_t * uint32_t queue_frames, uint32_t max_queue_frames, uint32_t samples_per_packet, - uint32_t samples_per_second) + uint32_t samples_per_second, + uint32_t max_drift) { if (!switch_rtp_ready(rtp_session)) { @@ -1921,7 +1921,7 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_activate_jitter_buffer(switch_rtp_t * if (rtp_session->jb) { stfu_n_resize(rtp_session->jb, queue_frames); } else { - rtp_session->jb = stfu_n_init(queue_frames, max_queue_frames ? max_queue_frames : 50, samples_per_packet, samples_per_second); + rtp_session->jb = stfu_n_init(queue_frames, max_queue_frames ? max_queue_frames : 50, samples_per_packet, samples_per_second, max_drift); } READ_DEC(rtp_session); @@ -2304,7 +2304,8 @@ static void do_2833(switch_rtp_t *rtp_session, switch_core_session_t *session) SWITCH_DECLARE(void) rtp_flush_read_buffer(switch_rtp_t *rtp_session, switch_rtp_flush_t flush) { - if (switch_rtp_ready(rtp_session) && !switch_test_flag(rtp_session, SWITCH_RTP_FLAG_PROXY_MEDIA)) { + if (switch_rtp_ready(rtp_session) && !switch_test_flag(rtp_session, SWITCH_RTP_FLAG_PROXY_MEDIA) && + !switch_test_flag(rtp_session, SWITCH_RTP_FLAG_VIDEO)) { switch_set_flag_locked(rtp_session, SWITCH_RTP_FLAG_FLUSH); switch (flush) { case SWITCH_RTP_FLUSH_STICK: @@ -2396,14 +2397,14 @@ static void do_flush(switch_rtp_t *rtp_session) #define return_cng_frame() do_cng = 1; goto timer_check -static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t *bytes, switch_frame_flag_t *flags) +static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t *bytes, switch_frame_flag_t *flags, switch_bool_t return_jb_packet) { switch_status_t status = SWITCH_STATUS_FALSE; stfu_frame_t *jb_frame; uint32_t ts; switch_assert(bytes); - + more: *bytes = sizeof(rtp_msg_t); status = switch_socket_recvfrom(rtp_session->from_addr, rtp_session->sock_input, 0, (void *) &rtp_session->recv_msg, bytes); ts = ntohl(rtp_session->recv_msg.header.ts); @@ -2490,14 +2491,21 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t stfu_n_reset(rtp_session->jb); } - stfu_n_eat(rtp_session->jb, rtp_session->last_read_ts, - rtp_session->recv_msg.header.pt, - rtp_session->recv_msg.body, *bytes - rtp_header_len, rtp_session->timer.samplecount); - *bytes = 0; + if (stfu_n_eat(rtp_session->jb, rtp_session->last_read_ts, + rtp_session->recv_msg.header.pt, + rtp_session->recv_msg.body, *bytes - rtp_header_len, rtp_session->timer.samplecount) == STFU_ITS_TOO_LATE) { + printf("doh\n"); + goto more; + } + status = SWITCH_STATUS_FALSE; + if (!return_jb_packet) { + return status; + } + *bytes = 0; } - if (rtp_session->jb && !rtp_session->pause_jb && !rtp_session->checked_jb) { + if (rtp_session->jb && !rtp_session->pause_jb) { if ((jb_frame = stfu_n_read_a_frame(rtp_session->jb))) { memcpy(rtp_session->recv_msg.body, jb_frame->data, jb_frame->dlen); @@ -2511,8 +2519,6 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t rtp_session->recv_msg.header.pt = jb_frame->pt; status = SWITCH_STATUS_SUCCESS; } - - rtp_session->checked_jb++; } return status; @@ -2657,8 +2663,6 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_ READ_INC(rtp_session); - rtp_session->checked_jb = 0; - while (switch_rtp_ready(rtp_session)) { int do_cng = 0; int read_pretriggered = 0; @@ -2668,17 +2672,19 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_ if ((switch_test_flag(rtp_session, SWITCH_RTP_FLAG_AUTOFLUSH) || switch_test_flag(rtp_session, SWITCH_RTP_FLAG_STICKY_FLUSH)) && rtp_session->read_pollfd) { if (switch_poll(rtp_session->read_pollfd, 1, &fdr, 0) == SWITCH_STATUS_SUCCESS) { - status = read_rtp_packet(rtp_session, &bytes, flags); - /* switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Initial %d\n", bytes); */ - read_pretriggered = 1; + status = read_rtp_packet(rtp_session, &bytes, flags, SWITCH_FALSE); + /* switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Initial (%i) %d\n", status, bytes); */ + if (status != SWITCH_STATUS_FALSE) { + read_pretriggered = 1; + } - if (switch_poll(rtp_session->read_pollfd, 1, &fdr, 0) == SWITCH_STATUS_SUCCESS) { - /* switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Trigger %d\n", rtp_session->hot_hits); */ - rtp_session->hot_hits += rtp_session->samples_per_interval; - } else { - rtp_session->hot_hits = 0; - switch_core_timer_sync(&rtp_session->timer); - goto recvfrom; + if (bytes) { + if (switch_poll(rtp_session->read_pollfd, 1, &fdr, 0) == SWITCH_STATUS_SUCCESS) { + /* switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Trigger %d\n", rtp_session->hot_hits); */ + rtp_session->hot_hits += rtp_session->samples_per_interval; + } else { + rtp_session->hot_hits = 0; + } } if (rtp_session->hot_hits >= rtp_session->samples_per_second * 5) { @@ -2737,9 +2743,11 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_ } if (poll_status == SWITCH_STATUS_SUCCESS) { - if (!read_pretriggered) { - status = read_rtp_packet(rtp_session, &bytes, flags); - /* switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Read bytes %d\n", bytes); */ + if (read_pretriggered) { + read_pretriggered = 0; + } else { + status = read_rtp_packet(rtp_session, &bytes, flags, SWITCH_TRUE); + /* switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Read bytes (%i) %d\n", status, bytes); */ } } else { if (!SWITCH_STATUS_IS_BREAK(poll_status) && poll_status != SWITCH_STATUS_TIMEOUT) { @@ -2848,6 +2856,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_ goto end; } + if (bytes && rtp_session->recv_msg.header.version == 2 && !switch_test_flag(rtp_session, SWITCH_RTP_FLAG_PROXY_MEDIA) && !switch_test_flag(rtp_session, SWITCH_RTP_FLAG_UDPTL) && rtp_session->recv_msg.header.pt != 13 && @@ -2883,10 +2892,12 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_ } if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_FLUSH)) { + if (!switch_test_flag(rtp_session, SWITCH_RTP_FLAG_VIDEO)) { do_flush(rtp_session); - switch_clear_flag_locked(rtp_session, SWITCH_RTP_FLAG_FLUSH); bytes = 0; } + switch_clear_flag_locked(rtp_session, SWITCH_RTP_FLAG_FLUSH); + } if (bytes && bytes < 5) { continue;