From b09c32c19a04a82a81c1bd532fe59dcb6a923f73 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Thu, 6 Jan 2011 09:51:17 -0500 Subject: [PATCH 01/29] freetdm: use /bin/sh and not /bin/bash in the bootstrap script --- libs/freetdm/bootstrap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/freetdm/bootstrap b/libs/freetdm/bootstrap index 8ca4856832..247d396da5 100755 --- a/libs/freetdm/bootstrap +++ b/libs/freetdm/bootstrap @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/sh autoheader libtoolize --force --copy aclocal From 46853d7f3d08b20ba518d7b596e6082a2d8d9945 Mon Sep 17 00:00:00 2001 From: Brian West Date: Thu, 6 Jan 2011 11:38:36 -0600 Subject: [PATCH 02/29] swigall and fix gitignore for new celt. --- libs/.gitignore | 1 + .../languages/mod_managed/freeswitch_wrap.cxx | 87 +++++++++++++++++++ src/mod/languages/mod_managed/managed/swig.cs | 54 ++++++++++++ 3 files changed, 142 insertions(+) diff --git a/libs/.gitignore b/libs/.gitignore index cc42ba4fa4..b31646500e 100644 --- a/libs/.gitignore +++ b/libs/.gitignore @@ -1001,6 +1001,7 @@ /unimrcp/build/acmacros/lt~obsolete.m4 /*.tar.gz /celt-0.7.1/ +/celt-0.10.0/ /flite-1.3.99/ /freeradius-client-1.1.6/ /iksemel/test/tst-dom diff --git a/src/mod/languages/mod_managed/freeswitch_wrap.cxx b/src/mod/languages/mod_managed/freeswitch_wrap.cxx index d05f4f1213..aa2a84f3f6 100644 --- a/src/mod/languages/mod_managed/freeswitch_wrap.cxx +++ b/src/mod/languages/mod_managed/freeswitch_wrap.cxx @@ -1422,6 +1422,17 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_SWITCH_HOLD_MUSIC_VARIABLE_get() { } +SWIGEXPORT char * SWIGSTDCALL CSharp_SWITCH_TEMP_HOLD_MUSIC_VARIABLE_get() { + char * jresult ; + char *result = 0 ; + + result = (char *) "temp_hold_music"; + + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + SWIGEXPORT char * SWIGSTDCALL CSharp_SWITCH_EXPORT_VARS_VARIABLE_get() { char * jresult ; char *result = 0 ; @@ -12304,6 +12315,30 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_is_digit_string(char * jarg1) { } +SWIGEXPORT char SWIGSTDCALL CSharp_switch_itodtmf(char jarg1) { + char jresult ; + char arg1 ; + char result; + + arg1 = (char)jarg1; + result = (char)switch_itodtmf(arg1); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_switch_dtmftoi(char * jarg1) { + int jresult ; + char *arg1 = (char *) 0 ; + int result; + + arg1 = (char *)jarg1; + result = (int)switch_dtmftoi(arg1); + jresult = result; + return jresult; +} + + SWIGEXPORT unsigned long SWIGSTDCALL CSharp_switch_known_bitrate(unsigned char jarg1) { unsigned long jresult ; switch_payload_t arg1 ; @@ -23501,6 +23536,30 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_switch_channel_get_variable_partner(void * } +SWIGEXPORT char * SWIGSTDCALL CSharp_switch_channel_get_hold_music(void * jarg1) { + char * jresult ; + switch_channel_t *arg1 = (switch_channel_t *) 0 ; + char *result = 0 ; + + arg1 = (switch_channel_t *)jarg1; + result = (char *)switch_channel_get_hold_music(arg1); + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + +SWIGEXPORT char * SWIGSTDCALL CSharp_switch_channel_get_hold_music_partner(void * jarg1) { + char * jresult ; + switch_channel_t *arg1 = (switch_channel_t *) 0 ; + char *result = 0 ; + + arg1 = (switch_channel_t *)jarg1; + result = (char *)switch_channel_get_hold_music_partner(arg1); + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + SWIGEXPORT int SWIGSTDCALL CSharp_switch_channel_export_variable_var_check(void * jarg1, char * jarg2, char * jarg3, char * jarg4, int jarg5) { int jresult ; switch_channel_t *arg1 = (switch_channel_t *) 0 ; @@ -23746,6 +23805,20 @@ SWIGEXPORT unsigned long SWIGSTDCALL CSharp_switch_channel_test_cap(void * jarg1 } +SWIGEXPORT unsigned long SWIGSTDCALL CSharp_switch_channel_test_cap_partner(void * jarg1, int jarg2) { + unsigned long jresult ; + switch_channel_t *arg1 = (switch_channel_t *) 0 ; + switch_channel_cap_t arg2 ; + uint32_t result; + + arg1 = (switch_channel_t *)jarg1; + arg2 = (switch_channel_cap_t)jarg2; + result = (uint32_t)switch_channel_test_cap_partner(arg1,arg2); + jresult = (unsigned long)result; + return jresult; +} + + SWIGEXPORT int SWIGSTDCALL CSharp_switch_channel_set_flag_partner(void * jarg1, int jarg2) { int jresult ; switch_channel_t *arg1 = (switch_channel_t *) 0 ; @@ -29077,6 +29150,20 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_rtp_deactivate_jitter_buffer(void * jar } +SWIGEXPORT int SWIGSTDCALL CSharp_switch_rtp_pause_jitter_buffer(void * jarg1, int jarg2) { + int jresult ; + switch_rtp_t *arg1 = (switch_rtp_t *) 0 ; + switch_bool_t arg2 ; + switch_status_t result; + + arg1 = (switch_rtp_t *)jarg1; + arg2 = (switch_bool_t)jarg2; + result = (switch_status_t)switch_rtp_pause_jitter_buffer(arg1,arg2); + jresult = result; + return jresult; +} + + SWIGEXPORT void SWIGSTDCALL CSharp_switch_rtp_set_flag(void * jarg1, unsigned long jarg2) { switch_rtp_t *arg1 = (switch_rtp_t *) 0 ; switch_rtp_flag_t arg2 ; diff --git a/src/mod/languages/mod_managed/managed/swig.cs b/src/mod/languages/mod_managed/managed/swig.cs index 849a6f62a4..5a2188ac83 100644 --- a/src/mod/languages/mod_managed/managed/swig.cs +++ b/src/mod/languages/mod_managed/managed/swig.cs @@ -2732,6 +2732,16 @@ public class freeswitch { return ret; } + public static char switch_itodtmf(char i) { + char ret = freeswitchPINVOKE.switch_itodtmf(i); + return ret; + } + + public static int switch_dtmftoi(string s) { + int ret = freeswitchPINVOKE.switch_dtmftoi(s); + return ret; + } + public static uint switch_known_bitrate(byte payload) { uint ret = freeswitchPINVOKE.switch_known_bitrate(payload); return ret; @@ -3281,6 +3291,16 @@ public class freeswitch { return ret; } + public static string switch_channel_get_hold_music(SWIGTYPE_p_switch_channel channel) { + string ret = freeswitchPINVOKE.switch_channel_get_hold_music(SWIGTYPE_p_switch_channel.getCPtr(channel)); + return ret; + } + + public static string switch_channel_get_hold_music_partner(SWIGTYPE_p_switch_channel channel) { + string ret = freeswitchPINVOKE.switch_channel_get_hold_music_partner(SWIGTYPE_p_switch_channel.getCPtr(channel)); + return ret; + } + public static switch_status_t switch_channel_export_variable_var_check(SWIGTYPE_p_switch_channel channel, string varname, string val, string export_varname, switch_bool_t var_check) { switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_channel_export_variable_var_check(SWIGTYPE_p_switch_channel.getCPtr(channel), varname, val, export_varname, (int)var_check); return ret; @@ -3369,6 +3389,11 @@ public class freeswitch { return ret; } + public static uint switch_channel_test_cap_partner(SWIGTYPE_p_switch_channel channel, switch_channel_cap_t cap) { + uint ret = freeswitchPINVOKE.switch_channel_test_cap_partner(SWIGTYPE_p_switch_channel.getCPtr(channel), (int)cap); + return ret; + } + public static switch_bool_t switch_channel_set_flag_partner(SWIGTYPE_p_switch_channel channel, switch_channel_flag_t flag) { switch_bool_t ret = (switch_bool_t)freeswitchPINVOKE.switch_channel_set_flag_partner(SWIGTYPE_p_switch_channel.getCPtr(channel), (int)flag); return ret; @@ -4664,6 +4689,11 @@ public class freeswitch { return ret; } + public static switch_status_t switch_rtp_pause_jitter_buffer(SWIGTYPE_p_switch_rtp rtp_session, switch_bool_t pause) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_rtp_pause_jitter_buffer(SWIGTYPE_p_switch_rtp.getCPtr(rtp_session), (int)pause); + return ret; + } + public static void switch_rtp_set_flag(SWIGTYPE_p_switch_rtp rtp_session, uint flags) { freeswitchPINVOKE.switch_rtp_set_flag(SWIGTYPE_p_switch_rtp.getCPtr(rtp_session), flags); } @@ -5418,6 +5448,7 @@ public class freeswitch { public static readonly string SWITCH_PROXY_MEDIA_VARIABLE = freeswitchPINVOKE.SWITCH_PROXY_MEDIA_VARIABLE_get(); public static readonly string SWITCH_ENDPOINT_DISPOSITION_VARIABLE = freeswitchPINVOKE.SWITCH_ENDPOINT_DISPOSITION_VARIABLE_get(); public static readonly string SWITCH_HOLD_MUSIC_VARIABLE = freeswitchPINVOKE.SWITCH_HOLD_MUSIC_VARIABLE_get(); + public static readonly string SWITCH_TEMP_HOLD_MUSIC_VARIABLE = freeswitchPINVOKE.SWITCH_TEMP_HOLD_MUSIC_VARIABLE_get(); public static readonly string SWITCH_EXPORT_VARS_VARIABLE = freeswitchPINVOKE.SWITCH_EXPORT_VARS_VARIABLE_get(); public static readonly string SWITCH_BRIDGE_EXPORT_VARS_VARIABLE = freeswitchPINVOKE.SWITCH_BRIDGE_EXPORT_VARS_VARIABLE_get(); public static readonly string SWITCH_R_SDP_VARIABLE = freeswitchPINVOKE.SWITCH_R_SDP_VARIABLE_get(); @@ -6006,6 +6037,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_SWITCH_HOLD_MUSIC_VARIABLE_get")] public static extern string SWITCH_HOLD_MUSIC_VARIABLE_get(); + [DllImport("mod_managed", EntryPoint="CSharp_SWITCH_TEMP_HOLD_MUSIC_VARIABLE_get")] + public static extern string SWITCH_TEMP_HOLD_MUSIC_VARIABLE_get(); + [DllImport("mod_managed", EntryPoint="CSharp_SWITCH_EXPORT_VARS_VARIABLE_get")] public static extern string SWITCH_EXPORT_VARS_VARIABLE_get(); @@ -8589,6 +8623,12 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_is_digit_string")] public static extern int switch_is_digit_string(string jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_itodtmf")] + public static extern char switch_itodtmf(char jarg1); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_dtmftoi")] + public static extern int switch_dtmftoi(string jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_known_bitrate")] public static extern uint switch_known_bitrate(byte jarg1); @@ -11310,6 +11350,12 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_get_variable_partner")] public static extern string switch_channel_get_variable_partner(HandleRef jarg1, string jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_get_hold_music")] + public static extern string switch_channel_get_hold_music(HandleRef jarg1); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_get_hold_music_partner")] + public static extern string switch_channel_get_hold_music_partner(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_export_variable_var_check")] public static extern int switch_channel_export_variable_var_check(HandleRef jarg1, string jarg2, string jarg3, string jarg4, int jarg5); @@ -11367,6 +11413,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_test_cap")] public static extern uint switch_channel_test_cap(HandleRef jarg1, int jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_test_cap_partner")] + public static extern uint switch_channel_test_cap_partner(HandleRef jarg1, int jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_set_flag_partner")] public static extern int switch_channel_set_flag_partner(HandleRef jarg1, int jarg2); @@ -12480,6 +12529,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_rtp_deactivate_jitter_buffer")] public static extern int switch_rtp_deactivate_jitter_buffer(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_rtp_pause_jitter_buffer")] + public static extern int switch_rtp_pause_jitter_buffer(HandleRef jarg1, int jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_rtp_set_flag")] public static extern void switch_rtp_set_flag(HandleRef jarg1, uint jarg2); @@ -21477,6 +21529,8 @@ public enum switch_channel_cap_t { CC_MEDIA_ACK = 1, CC_BYPASS_MEDIA, CC_PROXY_MEDIA, + CC_JITTERBUFFER, + CC_FS_RTP, CC_FLAG_MAX } From 0132cd3fc7dad74f480f01694d8db89207707020 Mon Sep 17 00:00:00 2001 From: Michael Jerris Date: Thu, 6 Jan 2011 15:35:12 -0600 Subject: [PATCH 03/29] Fix routing behavior of inbound calls from gateways that only match gateway based on the gw request uri param we now honor the extension gateway param only if it is explicitly set, but will not route to the username param if extension is not set also, new special value for extension "auto" that should use the request uri unless it has gw+ and then it will use the to uri --- src/mod/endpoints/mod_sofia/mod_sofia.h | 1 + src/mod/endpoints/mod_sofia/sofia.c | 44 +++++++++++++++++-------- 2 files changed, 32 insertions(+), 13 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index df267967fa..b6ce97dac6 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -403,6 +403,7 @@ struct sofia_gateway { char *register_from; char *register_contact; char *extension; + char *real_extension; char *register_to; char *register_proxy; char *register_sticky_proxy; diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 2643ceb17f..381eb5d2d1 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -2056,10 +2056,6 @@ static void parse_gateways(sofia_profile_t *profile, switch_xml_t gateways_tag) from_user = username; } - if (zstr(extension)) { - extension = username; - } - if (zstr(proxy)) { proxy = realm; } @@ -2151,8 +2147,13 @@ static void parse_gateways(sofia_profile_t *profile, switch_xml_t gateways_tag) sipip = profile->sipip; } - gateway->extension = switch_core_strdup(gateway->pool, extension); + if (zstr(extension)) { + extension = username; + } else { + gateway->real_extension = switch_core_strdup(gateway->pool, extension); + } + gateway->extension = switch_core_strdup(gateway->pool, extension); if (!strncasecmp(proxy, "sip:", 4)) { gateway->register_proxy = switch_core_strdup(gateway->pool, proxy); @@ -6222,6 +6223,7 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_ char acl_token[512] = ""; sofia_transport_t transport; const char *gw_name = NULL; + const char *gw_param_name = NULL; char *call_info_str = NULL; nua_handle_t *bnh = NULL; char sip_acl_authed_by[512] = ""; @@ -6854,7 +6856,7 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_ if (sip->sip_request->rq_url->url_params) { - gw_name = sofia_glue_find_parameter_value(session, sip->sip_request->rq_url->url_params, "gw="); + gw_param_name = sofia_glue_find_parameter_value(session, sip->sip_request->rq_url->url_params, "gw="); } if (strstr(destination_number, "gw+")) { @@ -6869,19 +6871,35 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_ } } - if (gw_name) { - sofia_gateway_t *gateway; - if (gw_name && (gateway = sofia_reg_find_gateway(gw_name))) { + if (gw_name || gw_param_name) { + sofia_gateway_t *gateway = NULL; + char *extension = NULL; + + if (gw_name && ((gateway = sofia_reg_find_gateway(gw_name)))) { + gw_param_name = NULL; + extension = gateway->extension; + } + + if (!gateway && gw_param_name) { + gateway = sofia_reg_find_gateway(gw_param_name); + extension = gateway->real_extension; + } + + if (gateway) { context = switch_core_session_strdup(session, gateway->register_context); switch_channel_set_variable(channel, "sip_gateway", gateway->name); - if (gateway->extension) { - if (!strcasecmp(gateway->extension, "auto_to_user")) { + if (!zstr(extension)) { + if (!strcasecmp(extension, "auto_to_user")) { destination_number = sip->sip_to->a_url->url_user; + } else if (!strcasecmp(extension, "auto")) { + if (gw_name) { + destination_number = sip->sip_to->a_url->url_user; + } } else { - destination_number = switch_core_session_strdup(session, gateway->extension); + destination_number = switch_core_session_strdup(session, extension); } - } else { + } else if (!gw_param_name) { destination_number = sip->sip_to->a_url->url_user; } From 9462f53c90beec68111bcd137f9415532aad5509 Mon Sep 17 00:00:00 2001 From: Michael Jerris Date: Thu, 6 Jan 2011 16:01:07 -0600 Subject: [PATCH 04/29] don't say we are not for polycom phones (safe rport) when its not really nat --- src/mod/endpoints/mod_sofia/sofia_reg.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c index 0b7d0f33fa..288191807c 100644 --- a/src/mod/endpoints/mod_sofia/sofia_reg.c +++ b/src/mod/endpoints/mod_sofia/sofia_reg.c @@ -1078,7 +1078,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand if (exptime && v_event && *v_event) { char *exp_var; char *allow_multireg = NULL; - int force_connectile = 0; + int auto_connectile = 0; allow_multireg = switch_event_get_header(*v_event, "sip-allow-multiple-registrations"); if (allow_multireg && switch_false(allow_multireg)) { @@ -1097,11 +1097,26 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand if (profile->rport_level == 3 && sip->sip_user_agent && sip->sip_user_agent->g_string && !strncasecmp(sip->sip_user_agent->g_string, "Polycom", 7)) { - force_connectile = 1; + if (sip && sip->sip_via) { + const char *host = sip->sip_via->v_host; + const char *c_port = sip->sip_via->v_port; + int port = 0; + + if (c_port) port = atoi(c_port); + if (!port) port = 5060; + + if (host && strcmp(network_ip, host)) { + auto_connectile = 1; + } else if (port != network_port) { + auto_connectile = 1; + } + } else { + auto_connectile = 1; + } } - if ((v_contact_str = switch_event_get_header(*v_event, "sip-force-contact")) || force_connectile) { - if ((!strcasecmp(v_contact_str, "NDLB-connectile-dysfunction-2.0")) || force_connectile) { + if ((v_contact_str = switch_event_get_header(*v_event, "sip-force-contact")) || auto_connectile) { + if ((!strcasecmp(v_contact_str, "NDLB-connectile-dysfunction-2.0")) || auto_connectile) { char *path_encoded; size_t path_encoded_len; char my_contact_str[1024]; From 85c22d10e2dc8f2d8303e4fd11219d9c4b09ccb5 Mon Sep 17 00:00:00 2001 From: Brian West Date: Thu, 6 Jan 2011 17:15:45 -0600 Subject: [PATCH 05/29] Fix iLBC when using ep_codec_string --- src/mod/codecs/mod_ilbc/mod_ilbc.c | 2 +- src/mod/endpoints/mod_sofia/sofia_glue.c | 57 ++++++++++++++++++++---- 2 files changed, 49 insertions(+), 10 deletions(-) diff --git a/src/mod/codecs/mod_ilbc/mod_ilbc.c b/src/mod/codecs/mod_ilbc/mod_ilbc.c index 4d52ba9944..23ca642c22 100644 --- a/src/mod/codecs/mod_ilbc/mod_ilbc.c +++ b/src/mod/codecs/mod_ilbc/mod_ilbc.c @@ -163,7 +163,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_ilbc_load) "mode=30", /* default fmtp to send (can be overridden by the init function) */ 8000, /* samples transferred per second */ 8000, /* actual samples transferred per second */ - 13300, /* bits transferred per second */ + 13330, /* bits transferred per second */ 30000, /* number of microseconds per frame */ ILBC_BLOCK_LEN_30MS, /* number of samples per frame */ ILBC_BLOCK_LEN_30MS * 2, /* number of bytes per frame decompressed */ diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 715b70f59d..ffba5ff0a3 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -3550,13 +3550,53 @@ void sofia_glue_set_r_sdp_codec_string(switch_core_session_t *session, const cha } if (match) { - if (ptime > 0) { - switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ",%s@%uh@%di", imp->iananame, (unsigned int) map->rm_rate, - ptime); - } else { - switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ",%s@%uh", imp->iananame, (unsigned int) map->rm_rate); + 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); } - already_did[imp->ianacode] = 1; + + 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), sizeof(buf) - strlen(buf), ",%s%s%s%s", map->rm_encoding, ratestr, ptstr, bitstr); + break; } } @@ -4378,6 +4418,7 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s 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) { @@ -4389,8 +4430,6 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s } } } - - for (i = first; i < last && i < tech_pvt->num_codecs; i++) { const switch_codec_implementation_t *imp = tech_pvt->codecs[i]; @@ -4401,7 +4440,7 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s } switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Audio Codec Compare [%s:%d:%u:%d:%u]/[%s:%d:%u:%d:%u]\n", - rm_encoding, map->rm_pt, (int) map->rm_rate, ptime, map_bit_rate, + rm_encoding, map->rm_pt, (int) map->rm_rate, codec_ms, map_bit_rate, imp->iananame, imp->ianacode, codec_rate, imp->microseconds_per_packet / 1000, bit_rate); 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; From 1a08df9b20d4b5c0e5bfc0ffe6d0b8d380aefd72 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 6 Jan 2011 17:41:17 -0600 Subject: [PATCH 06/29] add function to help set session read codec to slinear --- src/include/switch_core.h | 2 +- src/include/switch_module_interfaces.h | 8 +++++++ src/include/switch_types.h | 2 ++ src/switch_core_session.c | 33 ++++++++++++++++++++++++++ 4 files changed, 44 insertions(+), 1 deletion(-) diff --git a/src/include/switch_core.h b/src/include/switch_core.h index ff131acb17..29e8b43526 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -116,7 +116,6 @@ struct switch_core_session; struct switch_core_runtime; struct switch_core_port_allocator; - /*! \defgroup core1 Core Library \ingroup FREESWITCH @@ -713,6 +712,7 @@ SWITCH_DECLARE(void) switch_core_session_soft_lock(switch_core_session_t *sessio SWITCH_DECLARE(void) switch_core_session_soft_unlock(switch_core_session_t *session); SWITCH_DECLARE(void) switch_core_session_set_dmachine(switch_core_session_t *session, switch_ivr_dmachine_t *dmachine); SWITCH_DECLARE(switch_ivr_dmachine_t *) switch_core_session_get_dmachine(switch_core_session_t *session); +SWITCH_DECLARE(switch_status_t) switch_core_session_set_codec_slin(switch_core_session_t *session, switch_slin_data_t *data); /*! \brief Retrieve the unique identifier from the core diff --git a/src/include/switch_module_interfaces.h b/src/include/switch_module_interfaces.h index 1cf01c54bc..114e594c0c 100644 --- a/src/include/switch_module_interfaces.h +++ b/src/include/switch_module_interfaces.h @@ -711,6 +711,14 @@ struct switch_api_interface { #define PROTECT_INTERFACE(_it) if (_it) {switch_mutex_lock(_it->reflock); switch_thread_rwlock_rdlock(_it->parent->rwlock); switch_thread_rwlock_rdlock(_it->rwlock); _it->refs++; _it->parent->refs++; switch_mutex_unlock(_it->reflock);} //if (!strcmp(_it->interface_name, "user")) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "+++++++++++LOCK %s %d/%d\n", _it->interface_name, _it->refs, _it->parent->refs); #define UNPROTECT_INTERFACE(_it) if (_it) {switch_mutex_lock(_it->reflock); switch_thread_rwlock_unlock(_it->rwlock); switch_thread_rwlock_unlock(_it->parent->rwlock); _it->refs--; _it->parent->refs--; switch_mutex_unlock(_it->reflock);} //if (!strcmp(_it->interface_name, "user")) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "---------UNLOCK %s %d/%d\n", _it->interface_name, _it->refs, _it->parent->refs); +#include "switch_frame.h" + +struct switch_slin_data { + switch_core_session_t *session; + switch_frame_t write_frame; + switch_codec_t codec; + char frame_data[SWITCH_RECOMMENDED_BUFFER_SIZE]; +}; SWITCH_END_EXTERN_C #endif diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 01f890d51c..3fbf9c48a6 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -1817,6 +1817,8 @@ typedef struct switch_loadable_module_function_table { typedef int (*switch_modulename_callback_func_t) (void *user_data, const char *module_name); +typedef struct switch_slin_data switch_slin_data_t; + #define SWITCH_MODULE_DEFINITION_EX(name, load, shutdown, runtime, flags) \ static const char modname[] = #name ; \ SWITCH_MOD_DECLARE_DATA switch_loadable_module_function_table_t name##_module_interface = { \ diff --git a/src/switch_core_session.c b/src/switch_core_session.c index 9319abc535..4836aae73f 100644 --- a/src/switch_core_session.c +++ b/src/switch_core_session.c @@ -58,6 +58,39 @@ SWITCH_DECLARE(void) switch_core_session_soft_unlock(switch_core_session_t *sess session->soft_lock = 0; } +SWITCH_DECLARE(switch_status_t) switch_core_session_set_codec_slin(switch_core_session_t *session, switch_slin_data_t *data) + +{ + switch_codec_implementation_t read_impl = { 0 }; + int interval; + + switch_core_session_get_read_impl(session, &read_impl); + interval = read_impl.microseconds_per_packet / 1000; + data->session = session; + + if (switch_core_codec_init(&data->codec, + "L16", + NULL, + read_impl.actual_samples_per_second, + interval, + 1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, NULL) == SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), + SWITCH_LOG_DEBUG, "Codec Activated L16@%uhz %dms\n", read_impl.actual_samples_per_second, interval); + + memset(&data->write_frame, 0, sizeof(data->write_frame)); + + data->write_frame.codec = &data->codec; + data->write_frame.data = data->frame_data; + data->write_frame.buflen = sizeof(data->frame_data); + data->write_frame.datalen = 0; + switch_core_session_set_read_codec(session, &data->codec); + return SWITCH_STATUS_SUCCESS; + } + + return SWITCH_STATUS_FALSE; +} + + #ifdef SWITCH_DEBUG_RWLOCKS SWITCH_DECLARE(switch_core_session_t *) switch_core_session_perform_locate(const char *uuid_str, const char *file, const char *func, int line) #else From cd13030f25cc66b56edeb80c6631920a9aa970ff Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Thu, 6 Jan 2011 23:17:08 -0600 Subject: [PATCH 07/29] vs2010 reswig --- .../mod_managed/freeswitch_wrap.2010.cxx | 243 ++++++++++++++++++ .../mod_managed/managed/swig.2010.cs | 200 ++++++++++++++ 2 files changed, 443 insertions(+) diff --git a/src/mod/languages/mod_managed/freeswitch_wrap.2010.cxx b/src/mod/languages/mod_managed/freeswitch_wrap.2010.cxx index f5e9e31f72..9ebd6ff9df 100644 --- a/src/mod/languages/mod_managed/freeswitch_wrap.2010.cxx +++ b/src/mod/languages/mod_managed/freeswitch_wrap.2010.cxx @@ -1331,6 +1331,16 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_SWITCH_HOLD_MUSIC_VARIABLE_get() { } +SWIGEXPORT char * SWIGSTDCALL CSharp_SWITCH_TEMP_HOLD_MUSIC_VARIABLE_get() { + char * jresult ; + char *result = 0 ; + + result = (char *)("temp_hold_music"); + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + SWIGEXPORT char * SWIGSTDCALL CSharp_SWITCH_EXPORT_VARS_VARIABLE_get() { char * jresult ; char *result = 0 ; @@ -7112,6 +7122,20 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_switch_core_session_get_dmachine(void * jar } +SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_session_set_codec_slin(void * jarg1, void * jarg2) { + int jresult ; + switch_core_session_t *arg1 = (switch_core_session_t *) 0 ; + switch_slin_data_t *arg2 = (switch_slin_data_t *) 0 ; + switch_status_t result; + + arg1 = (switch_core_session_t *)jarg1; + arg2 = (switch_slin_data_t *)jarg2; + result = (switch_status_t)switch_core_session_set_codec_slin(arg1,arg2); + jresult = result; + return jresult; +} + + SWIGEXPORT char * SWIGSTDCALL CSharp_switch_core_get_uuid() { char * jresult ; char *result = 0 ; @@ -10392,6 +10416,18 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_cache_db_execute_sql_callback(void * ja } +SWIGEXPORT int SWIGSTDCALL CSharp_switch_cache_db_affected_rows(void * jarg1) { + int jresult ; + switch_cache_db_handle_t *arg1 = (switch_cache_db_handle_t *) 0 ; + int result; + + arg1 = (switch_cache_db_handle_t *)jarg1; + result = (int)switch_cache_db_affected_rows(arg1); + jresult = result; + return jresult; +} + + SWIGEXPORT void SWIGSTDCALL CSharp_switch_cache_db_status(void * jarg1) { switch_stream_handle_t *arg1 = (switch_stream_handle_t *) 0 ; @@ -11972,6 +12008,30 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_is_digit_string(char * jarg1) { } +SWIGEXPORT char SWIGSTDCALL CSharp_switch_itodtmf(char jarg1) { + char jresult ; + char arg1 ; + char result; + + arg1 = (char)jarg1; + result = (char)switch_itodtmf(arg1); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_switch_dtmftoi(char * jarg1) { + int jresult ; + char *arg1 = (char *) 0 ; + int result; + + arg1 = (char *)jarg1; + result = (int)switch_dtmftoi(arg1); + jresult = result; + return jresult; +} + + SWIGEXPORT unsigned long SWIGSTDCALL CSharp_switch_known_bitrate(unsigned char jarg1) { unsigned long jresult ; switch_payload_t arg1 ; @@ -22102,6 +22162,119 @@ SWIGEXPORT void SWIGSTDCALL CSharp_delete_switch_api_interface(void * jarg1) { } +SWIGEXPORT void SWIGSTDCALL CSharp_switch_slin_data_session_set(void * jarg1, void * jarg2) { + switch_slin_data *arg1 = (switch_slin_data *) 0 ; + switch_core_session_t *arg2 = (switch_core_session_t *) 0 ; + + arg1 = (switch_slin_data *)jarg1; + arg2 = (switch_core_session_t *)jarg2; + if (arg1) (arg1)->session = arg2; +} + + +SWIGEXPORT void * SWIGSTDCALL CSharp_switch_slin_data_session_get(void * jarg1) { + void * jresult ; + switch_slin_data *arg1 = (switch_slin_data *) 0 ; + switch_core_session_t *result = 0 ; + + arg1 = (switch_slin_data *)jarg1; + result = (switch_core_session_t *) ((arg1)->session); + jresult = (void *)result; + return jresult; +} + + +SWIGEXPORT void SWIGSTDCALL CSharp_switch_slin_data_write_frame_set(void * jarg1, void * jarg2) { + switch_slin_data *arg1 = (switch_slin_data *) 0 ; + switch_frame_t *arg2 = (switch_frame_t *) 0 ; + + arg1 = (switch_slin_data *)jarg1; + arg2 = (switch_frame_t *)jarg2; + if (arg1) (arg1)->write_frame = *arg2; +} + + +SWIGEXPORT void * SWIGSTDCALL CSharp_switch_slin_data_write_frame_get(void * jarg1) { + void * jresult ; + switch_slin_data *arg1 = (switch_slin_data *) 0 ; + switch_frame_t *result = 0 ; + + arg1 = (switch_slin_data *)jarg1; + result = (switch_frame_t *)& ((arg1)->write_frame); + jresult = (void *)result; + return jresult; +} + + +SWIGEXPORT void SWIGSTDCALL CSharp_switch_slin_data_codec_set(void * jarg1, void * jarg2) { + switch_slin_data *arg1 = (switch_slin_data *) 0 ; + switch_codec_t *arg2 = (switch_codec_t *) 0 ; + + arg1 = (switch_slin_data *)jarg1; + arg2 = (switch_codec_t *)jarg2; + if (arg1) (arg1)->codec = *arg2; +} + + +SWIGEXPORT void * SWIGSTDCALL CSharp_switch_slin_data_codec_get(void * jarg1) { + void * jresult ; + switch_slin_data *arg1 = (switch_slin_data *) 0 ; + switch_codec_t *result = 0 ; + + arg1 = (switch_slin_data *)jarg1; + result = (switch_codec_t *)& ((arg1)->codec); + jresult = (void *)result; + return jresult; +} + + +SWIGEXPORT void SWIGSTDCALL CSharp_switch_slin_data_frame_data_set(void * jarg1, char * jarg2) { + switch_slin_data *arg1 = (switch_slin_data *) 0 ; + char *arg2 ; + + arg1 = (switch_slin_data *)jarg1; + arg2 = (char *)jarg2; + { + if(arg2) { + strncpy((char*)arg1->frame_data, (const char *)arg2, 4096-1); + arg1->frame_data[4096-1] = 0; + } else { + arg1->frame_data[0] = 0; + } + } +} + + +SWIGEXPORT char * SWIGSTDCALL CSharp_switch_slin_data_frame_data_get(void * jarg1) { + char * jresult ; + switch_slin_data *arg1 = (switch_slin_data *) 0 ; + char *result = 0 ; + + arg1 = (switch_slin_data *)jarg1; + result = (char *)(char *) ((arg1)->frame_data); + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + +SWIGEXPORT void * SWIGSTDCALL CSharp_new_switch_slin_data() { + void * jresult ; + switch_slin_data *result = 0 ; + + result = (switch_slin_data *)new switch_slin_data(); + jresult = (void *)result; + return jresult; +} + + +SWIGEXPORT void SWIGSTDCALL CSharp_delete_switch_slin_data(void * jarg1) { + switch_slin_data *arg1 = (switch_slin_data *) 0 ; + + arg1 = (switch_slin_data *)jarg1; + delete arg1; +} + + SWIGEXPORT void SWIGSTDCALL CSharp_switch_channel_timetable_profile_created_set(void * jarg1, void * jarg2) { switch_channel_timetable *arg1 = (switch_channel_timetable *) 0 ; switch_time_t arg2 ; @@ -22834,6 +23007,30 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_switch_channel_get_variable_partner(void * } +SWIGEXPORT char * SWIGSTDCALL CSharp_switch_channel_get_hold_music(void * jarg1) { + char * jresult ; + switch_channel_t *arg1 = (switch_channel_t *) 0 ; + char *result = 0 ; + + arg1 = (switch_channel_t *)jarg1; + result = (char *)switch_channel_get_hold_music(arg1); + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + +SWIGEXPORT char * SWIGSTDCALL CSharp_switch_channel_get_hold_music_partner(void * jarg1) { + char * jresult ; + switch_channel_t *arg1 = (switch_channel_t *) 0 ; + char *result = 0 ; + + arg1 = (switch_channel_t *)jarg1; + result = (char *)switch_channel_get_hold_music_partner(arg1); + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + SWIGEXPORT int SWIGSTDCALL CSharp_switch_channel_export_variable_var_check(void * jarg1, char * jarg2, char * jarg3, char * jarg4, int jarg5) { int jresult ; switch_channel_t *arg1 = (switch_channel_t *) 0 ; @@ -23079,6 +23276,20 @@ SWIGEXPORT unsigned long SWIGSTDCALL CSharp_switch_channel_test_cap(void * jarg1 } +SWIGEXPORT unsigned long SWIGSTDCALL CSharp_switch_channel_test_cap_partner(void * jarg1, int jarg2) { + unsigned long jresult ; + switch_channel_t *arg1 = (switch_channel_t *) 0 ; + switch_channel_cap_t arg2 ; + uint32_t result; + + arg1 = (switch_channel_t *)jarg1; + arg2 = (switch_channel_cap_t)jarg2; + result = (uint32_t)switch_channel_test_cap_partner(arg1,arg2); + jresult = (unsigned long)result; + return jresult; +} + + SWIGEXPORT int SWIGSTDCALL CSharp_switch_channel_set_flag_partner(void * jarg1, int jarg2) { int jresult ; switch_channel_t *arg1 = (switch_channel_t *) 0 ; @@ -28362,6 +28573,20 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_rtp_deactivate_jitter_buffer(void * jar } +SWIGEXPORT int SWIGSTDCALL CSharp_switch_rtp_pause_jitter_buffer(void * jarg1, int jarg2) { + int jresult ; + switch_rtp_t *arg1 = (switch_rtp_t *) 0 ; + switch_bool_t arg2 ; + switch_status_t result; + + arg1 = (switch_rtp_t *)jarg1; + arg2 = (switch_bool_t)jarg2; + result = (switch_status_t)switch_rtp_pause_jitter_buffer(arg1,arg2); + jresult = result; + return jresult; +} + + SWIGEXPORT void SWIGSTDCALL CSharp_switch_rtp_set_flag(void * jarg1, unsigned long jarg2) { switch_rtp_t *arg1 = (switch_rtp_t *) 0 ; switch_rtp_flag_t arg2 ; @@ -33252,6 +33477,24 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_CoreSession_voice_name_get(void * jarg1) { } +SWIGEXPORT int SWIGSTDCALL CSharp_CoreSession_insertFile(void * jarg1, char * jarg2, char * jarg3, int jarg4) { + int jresult ; + CoreSession *arg1 = (CoreSession *) 0 ; + char *arg2 = (char *) 0 ; + char *arg3 = (char *) 0 ; + int arg4 ; + int result; + + arg1 = (CoreSession *)jarg1; + arg2 = (char *)jarg2; + arg3 = (char *)jarg3; + arg4 = (int)jarg4; + result = (int)(arg1)->insertFile((char const *)arg2,(char const *)arg3,arg4); + jresult = result; + return jresult; +} + + SWIGEXPORT int SWIGSTDCALL CSharp_CoreSession_Answer(void * jarg1) { int jresult ; CoreSession *arg1 = (CoreSession *) 0 ; diff --git a/src/mod/languages/mod_managed/managed/swig.2010.cs b/src/mod/languages/mod_managed/managed/swig.2010.cs index b792fb0ac8..059fb89a1c 100644 --- a/src/mod/languages/mod_managed/managed/swig.2010.cs +++ b/src/mod/languages/mod_managed/managed/swig.2010.cs @@ -224,6 +224,11 @@ public class CoreSession : IDisposable { } } + public int insertFile(string file, string insert_file, int sample_point) { + int ret = freeswitchPINVOKE.CoreSession_insertFile(swigCPtr, file, insert_file, sample_point); + return ret; + } + public int Answer() { int ret = freeswitchPINVOKE.CoreSession_Answer(swigCPtr); return ret; @@ -1362,6 +1367,11 @@ public class freeswitch { return ret; } + public static switch_status_t switch_core_session_set_codec_slin(SWIGTYPE_p_switch_core_session session, switch_slin_data data) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_core_session_set_codec_slin(SWIGTYPE_p_switch_core_session.getCPtr(session), switch_slin_data.getCPtr(data)); + return ret; + } + public static string switch_core_get_uuid() { string ret = freeswitchPINVOKE.switch_core_get_uuid(); return ret; @@ -2338,6 +2348,11 @@ public class freeswitch { 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)); + return ret; + } + public static void switch_cache_db_status(switch_stream_handle stream) { freeswitchPINVOKE.switch_cache_db_status(switch_stream_handle.getCPtr(stream)); } @@ -2732,6 +2747,16 @@ public class freeswitch { return ret; } + public static char switch_itodtmf(char i) { + char ret = freeswitchPINVOKE.switch_itodtmf(i); + return ret; + } + + public static int switch_dtmftoi(string s) { + int ret = freeswitchPINVOKE.switch_dtmftoi(s); + return ret; + } + public static uint switch_known_bitrate(byte payload) { uint ret = freeswitchPINVOKE.switch_known_bitrate(payload); return ret; @@ -3281,6 +3306,16 @@ public class freeswitch { return ret; } + public static string switch_channel_get_hold_music(SWIGTYPE_p_switch_channel channel) { + string ret = freeswitchPINVOKE.switch_channel_get_hold_music(SWIGTYPE_p_switch_channel.getCPtr(channel)); + return ret; + } + + public static string switch_channel_get_hold_music_partner(SWIGTYPE_p_switch_channel channel) { + string ret = freeswitchPINVOKE.switch_channel_get_hold_music_partner(SWIGTYPE_p_switch_channel.getCPtr(channel)); + return ret; + } + public static switch_status_t switch_channel_export_variable_var_check(SWIGTYPE_p_switch_channel channel, string varname, string val, string export_varname, switch_bool_t var_check) { switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_channel_export_variable_var_check(SWIGTYPE_p_switch_channel.getCPtr(channel), varname, val, export_varname, (int)var_check); return ret; @@ -3369,6 +3404,11 @@ public class freeswitch { return ret; } + public static uint switch_channel_test_cap_partner(SWIGTYPE_p_switch_channel channel, switch_channel_cap_t cap) { + uint ret = freeswitchPINVOKE.switch_channel_test_cap_partner(SWIGTYPE_p_switch_channel.getCPtr(channel), (int)cap); + return ret; + } + public static switch_bool_t switch_channel_set_flag_partner(SWIGTYPE_p_switch_channel channel, switch_channel_flag_t flag) { switch_bool_t ret = (switch_bool_t)freeswitchPINVOKE.switch_channel_set_flag_partner(SWIGTYPE_p_switch_channel.getCPtr(channel), (int)flag); return ret; @@ -4664,6 +4704,11 @@ public class freeswitch { return ret; } + public static switch_status_t switch_rtp_pause_jitter_buffer(SWIGTYPE_p_switch_rtp rtp_session, switch_bool_t pause) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_rtp_pause_jitter_buffer(SWIGTYPE_p_switch_rtp.getCPtr(rtp_session), (int)pause); + return ret; + } + public static void switch_rtp_set_flag(SWIGTYPE_p_switch_rtp rtp_session, uint flags) { freeswitchPINVOKE.switch_rtp_set_flag(SWIGTYPE_p_switch_rtp.getCPtr(rtp_session), flags); } @@ -5418,6 +5463,7 @@ public class freeswitch { public static readonly string SWITCH_PROXY_MEDIA_VARIABLE = freeswitchPINVOKE.SWITCH_PROXY_MEDIA_VARIABLE_get(); public static readonly string SWITCH_ENDPOINT_DISPOSITION_VARIABLE = freeswitchPINVOKE.SWITCH_ENDPOINT_DISPOSITION_VARIABLE_get(); public static readonly string SWITCH_HOLD_MUSIC_VARIABLE = freeswitchPINVOKE.SWITCH_HOLD_MUSIC_VARIABLE_get(); + public static readonly string SWITCH_TEMP_HOLD_MUSIC_VARIABLE = freeswitchPINVOKE.SWITCH_TEMP_HOLD_MUSIC_VARIABLE_get(); public static readonly string SWITCH_EXPORT_VARS_VARIABLE = freeswitchPINVOKE.SWITCH_EXPORT_VARS_VARIABLE_get(); public static readonly string SWITCH_BRIDGE_EXPORT_VARS_VARIABLE = freeswitchPINVOKE.SWITCH_BRIDGE_EXPORT_VARS_VARIABLE_get(); public static readonly string SWITCH_R_SDP_VARIABLE = freeswitchPINVOKE.SWITCH_R_SDP_VARIABLE_get(); @@ -6010,6 +6056,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_SWITCH_HOLD_MUSIC_VARIABLE_get")] public static extern string SWITCH_HOLD_MUSIC_VARIABLE_get(); + [DllImport("mod_managed", EntryPoint="CSharp_SWITCH_TEMP_HOLD_MUSIC_VARIABLE_get")] + public static extern string SWITCH_TEMP_HOLD_MUSIC_VARIABLE_get(); + [DllImport("mod_managed", EntryPoint="CSharp_SWITCH_EXPORT_VARS_VARIABLE_get")] public static extern string SWITCH_EXPORT_VARS_VARIABLE_get(); @@ -7474,6 +7523,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_get_dmachine")] public static extern IntPtr switch_core_session_get_dmachine(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_set_codec_slin")] + public static extern int switch_core_session_set_codec_slin(HandleRef jarg1, HandleRef jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_get_uuid")] public static extern string switch_core_get_uuid(); @@ -8218,6 +8270,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_execute_sql_callback")] public static extern int switch_cache_db_execute_sql_callback(HandleRef jarg1, string jarg2, HandleRef jarg3, HandleRef jarg4, ref string jarg5); + [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_affected_rows")] + public static extern int switch_cache_db_affected_rows(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_status")] public static extern void switch_cache_db_status(HandleRef jarg1); @@ -8590,6 +8645,12 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_is_digit_string")] public static extern int switch_is_digit_string(string jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_itodtmf")] + public static extern char switch_itodtmf(char jarg1); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_dtmftoi")] + public static extern int switch_dtmftoi(string jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_known_bitrate")] public static extern uint switch_known_bitrate(byte jarg1); @@ -11149,6 +11210,36 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_delete_switch_api_interface")] public static extern void delete_switch_api_interface(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_slin_data_session_set")] + public static extern void switch_slin_data_session_set(HandleRef jarg1, HandleRef jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_slin_data_session_get")] + public static extern IntPtr switch_slin_data_session_get(HandleRef jarg1); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_slin_data_write_frame_set")] + public static extern void switch_slin_data_write_frame_set(HandleRef jarg1, HandleRef jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_slin_data_write_frame_get")] + public static extern IntPtr switch_slin_data_write_frame_get(HandleRef jarg1); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_slin_data_codec_set")] + public static extern void switch_slin_data_codec_set(HandleRef jarg1, HandleRef jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_slin_data_codec_get")] + public static extern IntPtr switch_slin_data_codec_get(HandleRef jarg1); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_slin_data_frame_data_set")] + public static extern void switch_slin_data_frame_data_set(HandleRef jarg1, string jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_slin_data_frame_data_get")] + public static extern string switch_slin_data_frame_data_get(HandleRef jarg1); + + [DllImport("mod_managed", EntryPoint="CSharp_new_switch_slin_data")] + public static extern IntPtr new_switch_slin_data(); + + [DllImport("mod_managed", EntryPoint="CSharp_delete_switch_slin_data")] + public static extern void delete_switch_slin_data(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_timetable_profile_created_set")] public static extern void switch_channel_timetable_profile_created_set(HandleRef jarg1, HandleRef jarg2); @@ -11311,6 +11402,12 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_get_variable_partner")] public static extern string switch_channel_get_variable_partner(HandleRef jarg1, string jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_get_hold_music")] + public static extern string switch_channel_get_hold_music(HandleRef jarg1); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_get_hold_music_partner")] + public static extern string switch_channel_get_hold_music_partner(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_export_variable_var_check")] public static extern int switch_channel_export_variable_var_check(HandleRef jarg1, string jarg2, string jarg3, string jarg4, int jarg5); @@ -11368,6 +11465,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_test_cap")] public static extern uint switch_channel_test_cap(HandleRef jarg1, int jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_test_cap_partner")] + public static extern uint switch_channel_test_cap_partner(HandleRef jarg1, int jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_set_flag_partner")] public static extern int switch_channel_set_flag_partner(HandleRef jarg1, int jarg2); @@ -12481,6 +12581,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_rtp_deactivate_jitter_buffer")] public static extern int switch_rtp_deactivate_jitter_buffer(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_rtp_pause_jitter_buffer")] + public static extern int switch_rtp_pause_jitter_buffer(HandleRef jarg1, int jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_rtp_set_flag")] public static extern void switch_rtp_set_flag(HandleRef jarg1, uint jarg2); @@ -13672,6 +13775,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_CoreSession_voice_name_get")] public static extern string CoreSession_voice_name_get(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_CoreSession_insertFile")] + public static extern int CoreSession_insertFile(HandleRef jarg1, string jarg2, string jarg3, int jarg4); + [DllImport("mod_managed", EntryPoint="CSharp_CoreSession_Answer")] public static extern int CoreSession_Answer(HandleRef jarg1); @@ -21515,6 +21621,8 @@ public enum switch_channel_cap_t { CC_MEDIA_ACK = 1, CC_BYPASS_MEDIA, CC_PROXY_MEDIA, + CC_JITTERBUFFER, + CC_FS_RTP, CC_FLAG_MAX } @@ -29531,6 +29639,98 @@ public enum switch_signal_t { namespace FreeSWITCH.Native { +using System; +using System.Runtime.InteropServices; + +public class switch_slin_data : IDisposable { + private HandleRef swigCPtr; + protected bool swigCMemOwn; + + internal switch_slin_data(IntPtr cPtr, bool cMemoryOwn) { + swigCMemOwn = cMemoryOwn; + swigCPtr = new HandleRef(this, cPtr); + } + + internal static HandleRef getCPtr(switch_slin_data obj) { + return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr; + } + + ~switch_slin_data() { + Dispose(); + } + + public virtual void Dispose() { + lock(this) { + if (swigCPtr.Handle != IntPtr.Zero) { + if (swigCMemOwn) { + swigCMemOwn = false; + freeswitchPINVOKE.delete_switch_slin_data(swigCPtr); + } + swigCPtr = new HandleRef(null, IntPtr.Zero); + } + GC.SuppressFinalize(this); + } + } + + public SWIGTYPE_p_switch_core_session session { + set { + freeswitchPINVOKE.switch_slin_data_session_set(swigCPtr, SWIGTYPE_p_switch_core_session.getCPtr(value)); + } + get { + IntPtr cPtr = freeswitchPINVOKE.switch_slin_data_session_get(swigCPtr); + SWIGTYPE_p_switch_core_session ret = (cPtr == IntPtr.Zero) ? null : new SWIGTYPE_p_switch_core_session(cPtr, false); + return ret; + } + } + + public switch_frame write_frame { + set { + freeswitchPINVOKE.switch_slin_data_write_frame_set(swigCPtr, switch_frame.getCPtr(value)); + } + get { + IntPtr cPtr = freeswitchPINVOKE.switch_slin_data_write_frame_get(swigCPtr); + switch_frame ret = (cPtr == IntPtr.Zero) ? null : new switch_frame(cPtr, false); + return ret; + } + } + + public switch_codec codec { + set { + freeswitchPINVOKE.switch_slin_data_codec_set(swigCPtr, switch_codec.getCPtr(value)); + } + get { + IntPtr cPtr = freeswitchPINVOKE.switch_slin_data_codec_get(swigCPtr); + switch_codec ret = (cPtr == IntPtr.Zero) ? null : new switch_codec(cPtr, false); + return ret; + } + } + + public string frame_data { + set { + freeswitchPINVOKE.switch_slin_data_frame_data_set(swigCPtr, value); + } + get { + string ret = freeswitchPINVOKE.switch_slin_data_frame_data_get(swigCPtr); + return ret; + } + } + + public switch_slin_data() : this(freeswitchPINVOKE.new_switch_slin_data(), 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 { + [System.Flags] public enum switch_speech_flag_enum_t { SWITCH_SPEECH_FLAG_NONE = 0, SWITCH_SPEECH_FLAG_HASTEXT = (1 << 0), From b3fc001e6cfcfd9219374d13f996981405506118 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 7 Jan 2011 16:04:24 -0600 Subject: [PATCH 08/29] add rtp_bug IGNORE_DTMF_DURATION to speed up dtmf detection of RFC2833 on strange carriers --- src/include/switch_types.h | 8 +++-- src/mod/endpoints/mod_sofia/sofia_glue.c | 8 +++++ src/switch_rtp.c | 42 ++++++++++++++++++------ 3 files changed, 46 insertions(+), 12 deletions(-) diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 3fbf9c48a6..9a5e09db7c 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -632,9 +632,13 @@ typedef enum { This flag will never send any. Sheesh.... */ + RTP_BUG_IGNORE_DTMF_DURATION = (1 << 6) - - + /* + Guess Who? ... Yep, Sonus (and who know's who else) likes to interweave DTMF with the audio stream making it take + 2X as long as it should and sending an incorrect duration making the DTMF very delayed. + This flag will treat every dtmf as if it were 50ms and queue it on recipt of the leading packet rather than at the end. + */ } switch_rtp_bug_flag_t; diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index ffba5ff0a3..a529844059 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -6188,6 +6188,14 @@ void sofia_glue_parse_rtp_bugs(uint32_t *flag_pole, const char *str) if (switch_stristr("~NEVER_SEND_MARKER", str)) { *flag_pole &= ~RTP_BUG_NEVER_SEND_MARKER; } + + if (switch_stristr("IGNORE_DTMF_DURATION", str)) { + *flag_pole |= RTP_BUG_IGNORE_DTMF_DURATION; + } + + if (switch_stristr("~IGNORE_DTMF_DURATION", str)) { + *flag_pole &= ~RTP_BUG_IGNORE_DTMF_DURATION; + } } char *sofia_glue_gen_contact_str(sofia_profile_t *profile, sip_t const *sip, sofia_nat_parse_t *np) diff --git a/src/switch_rtp.c b/src/switch_rtp.c index 41d5fc98dd..eb8b6a19d3 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -133,6 +133,7 @@ struct switch_rtp_rfc2833_data { char last_digit; switch_queue_t *dtmf_inqueue; switch_mutex_t *dtmf_mutex; + uint8_t in_digit_queued; }; struct switch_rtp { @@ -2479,7 +2480,8 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_ } } - if ((!(io_flags & SWITCH_IO_FLAG_NOBLOCK)) && (rtp_session->dtmf_data.out_digit_dur == 0 || switch_test_flag(rtp_session, SWITCH_RTP_FLAG_VIDEO))) { + if ((!(io_flags & SWITCH_IO_FLAG_NOBLOCK)) && + (rtp_session->dtmf_data.out_digit_dur == 0 || switch_test_flag(rtp_session, SWITCH_RTP_FLAG_VIDEO))) { return_cng_frame(); } } @@ -2819,7 +2821,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_ } #ifdef DEBUG_2833 if (rtp_session->dtmf_data.in_digit_sanity && !(rtp_session->dtmf_data.in_digit_sanity % 100)) { - printf("sanity %d\n", rtp_session->dtmf_data.in_digit_sanity); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "sanity %d\n", rtp_session->dtmf_data.in_digit_sanity); } #endif @@ -2869,7 +2871,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_ } } #ifdef DEBUG_2833 - printf("packet[%d]: %02x %02x %02x %02x\n", (int) len, (unsigned) packet[0], (unsigned) + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "packet[%d]: %02x %02x %02x %02x\n", (int) len, (unsigned) packet[0], (unsigned) packet[1], (unsigned) packet[2], (unsigned) packet[3]); #endif @@ -2878,16 +2880,28 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_ rtp_session->dtmf_data.in_digit_seq = in_digit_seq; #ifdef DEBUG_2833 - printf("read: %c %u %u %u %u %d %d %s\n", + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "read: %c %u %u %u %u %d %d %s\n", key, in_digit_seq, rtp_session->dtmf_data.in_digit_seq, ts, duration, rtp_session->recv_msg.header.m, end, end && !rtp_session->dtmf_data.in_digit_ts ? "ignored" : ""); #endif + + if (!rtp_session->dtmf_data.in_digit_queued && (rtp_session->rtp_bugs & RTP_BUG_IGNORE_DTMF_DURATION) && + rtp_session->dtmf_data.in_digit_ts) { + switch_dtmf_t dtmf = { key, switch_core_min_dtmf_duration(0) }; +#ifdef DEBUG_2833 + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Early Queuing digit %c:%d\n", dtmf.digit, dtmf.duration / 8); +#endif + switch_rtp_queue_rfc2833_in(rtp_session, &dtmf); + rtp_session->dtmf_data.in_digit_queued = 1; + } + /* only set sanity if we do NOT ignore the packet */ if (rtp_session->dtmf_data.in_digit_ts) { rtp_session->dtmf_data.in_digit_sanity = 2000; } - if (rtp_session->dtmf_data.last_duration > duration && rtp_session->dtmf_data.last_duration > 0xFC17 && ts == rtp_session->dtmf_data.in_digit_ts) { + if (rtp_session->dtmf_data.last_duration > duration && + rtp_session->dtmf_data.last_duration > 0xFC17 && ts == rtp_session->dtmf_data.in_digit_ts) { rtp_session->dtmf_data.flip++; } @@ -2902,18 +2916,26 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_ dtmf.duration += rtp_session->dtmf_data.flip * 0xFFFF; rtp_session->dtmf_data.flip = 0; #ifdef DEBUG_2833 - printf("you're welcome!\n"); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "you're welcome!\n"); #endif } #ifdef DEBUG_2833 - printf("done digit=%c ts=%u start_ts=%u dur=%u ddur=%u\n", + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "done digit=%c ts=%u start_ts=%u dur=%u ddur=%u\n", dtmf.digit, ts, rtp_session->dtmf_data.in_digit_ts, duration, dtmf.duration); #endif - switch_rtp_queue_rfc2833_in(rtp_session, &dtmf); + + if (!(rtp_session->rtp_bugs & RTP_BUG_IGNORE_DTMF_DURATION) && !rtp_session->dtmf_data.in_digit_queued) { +#ifdef DEBUG_2833 + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Queuing digit %c:%d\n", dtmf.digit, dtmf.duration / 8); +#endif + switch_rtp_queue_rfc2833_in(rtp_session, &dtmf); + } + rtp_session->dtmf_data.last_digit = rtp_session->dtmf_data.first_digit; rtp_session->dtmf_data.in_digit_ts = 0; rtp_session->dtmf_data.in_digit_sanity = 0; + rtp_session->dtmf_data.in_digit_queued = 0; do_cng = 1; } else { if (!switch_rtp_ready(rtp_session)) { @@ -2932,7 +2954,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_ rtp_session->dtmf_data.last_duration = duration; } else { #ifdef DEBUG_2833 - printf("drop: %c %u %u %u %u %d %d\n", + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "drop: %c %u %u %u %u %d %d\n", key, in_digit_seq, rtp_session->dtmf_data.in_digit_seq, ts, duration, rtp_session->recv_msg.header.m, end); #endif switch_cond_next(); @@ -3540,7 +3562,7 @@ static int rtp_common_write(switch_rtp_t *rtp_session, #ifdef RTP_DEBUG_WRITE_DELTA { int delta = (int) (now - rtp_session->send_time) / 1000; - printf("WRITE %d delta %d\n", (int) bytes, delta); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "WRITE %d delta %d\n", (int) bytes, delta); } #endif rtp_session->send_time = now; From 01024acee13d2d6343bee07f8b6de3e8a1efeb82 Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Fri, 7 Jan 2011 17:46:17 -0500 Subject: [PATCH 09/29] Freetdm - ISDN fix for ani2 not decoded properly --- .../ftmod_sangoma_isdn_stack_hndl.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) 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 912d061963..2b43e9cea5 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 @@ -133,13 +133,12 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event) get_redir_num(ftdmchan, &conEvnt->redirNmb); get_calling_subaddr(ftdmchan, &conEvnt->cgPtySad); get_prog_ind_ie(ftdmchan, &conEvnt->progInd); - get_facility_ie(ftdmchan, &conEvnt->facilityStr); + get_facility_ie(ftdmchan, &conEvnt->facilityStr); if (get_calling_name_from_display(ftdmchan, &conEvnt->display) != FTDM_SUCCESS) { get_calling_name_from_usr_usr(ftdmchan, &conEvnt->usrUsr); } - ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Incoming call: Called No:[%s] Calling No:[%s]\n", ftdmchan->caller_data.dnis.digits, ftdmchan->caller_data.cid_num.digits); if (conEvnt->bearCap[0].eh.pres) { @@ -147,10 +146,17 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event) ftdmchan->caller_data.bearer_capability = sngisdn_get_infoTranCap_from_stack(conEvnt->bearCap[0].infoTranCap.val); } - if (conEvnt->shift11.eh.pres && conEvnt->ni2OctStr.eh.pres) { if (conEvnt->ni2OctStr.str.len == 4 && conEvnt->ni2OctStr.str.val[0] == 0x37) { - snprintf(ftdmchan->caller_data.aniII, 5, "%.2d", conEvnt->ni2OctStr.str.val[3]); + uint8_t encoding = (conEvnt->ni2OctStr.str.val[2] >> 5); + if (encoding == 0 || encoding == 1) { + /* BCD even or BCD odd */ + uint8_t value = (conEvnt->ni2OctStr.str.val[3] & 0x0F)*10 + ((conEvnt->ni2OctStr.str.val[3] >> 4) & 0x0F); + snprintf(ftdmchan->caller_data.aniII, 5, "%.2d", value); + } else if (encoding == 2) { + /* IA 5 */ + snprintf(ftdmchan->caller_data.aniII, 5, "%c", conEvnt->ni2OctStr.str.val[3]); + } } } From a8b2840f2b3a634ebda4a601700c8502c2611045 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 7 Jan 2011 17:53:09 -0600 Subject: [PATCH 10/29] little more on the DTMF commit --- src/switch_rtp.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/switch_rtp.c b/src/switch_rtp.c index eb8b6a19d3..04d5940167 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -126,6 +126,7 @@ struct switch_rtp_rfc2833_data { uint16_t in_digit_seq; uint32_t in_digit_ts; uint32_t in_digit_sanity; + uint32_t in_interleaved; uint32_t timestamp_dtmf; uint16_t last_duration; uint32_t flip; @@ -2962,11 +2963,28 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_ } } + if (rtp_session->dtmf_data.in_digit_ts) { + + } + + if (rtp_session->dtmf_data.in_digit_ts) { if (!switch_rtp_ready(rtp_session)) { goto end; } - return_cng_frame(); + + if (!rtp_session->dtmf_data.in_interleaved && rtp_session->recv_msg.header.pt != rtp_session->recv_te) { + /* Drat, they are sending audio still as well as DTMF ok fine..... *sigh* */ + rtp_session->dtmf_data.in_interleaved = 1; + } + + if (rtp_session->dtmf_data.in_interleaved || (rtp_session->rtp_bugs & RTP_BUG_IGNORE_DTMF_DURATION)) { + if (rtp_session->recv_msg.header.pt == rtp_session->recv_te) { + goto recvfrom; + } + } else { + return_cng_frame(); + } } timer_check: @@ -3276,7 +3294,6 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_zerocopy_read_frame(switch_rtp_t *rtp } frame->datalen = bytes; - return SWITCH_STATUS_SUCCESS; } From 300348916ed9417dd16e7fa041ba56676ae08f1b Mon Sep 17 00:00:00 2001 From: Andrew Thompson Date: Sun, 9 Jan 2011 14:42:42 -0500 Subject: [PATCH 11/29] Log error when there's no IVR menus configured when you call 'ivr' DP app --- src/mod/applications/mod_dptools/mod_dptools.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c index 4602dd2bc5..41417255bb 100755 --- a/src/mod/applications/mod_dptools/mod_dptools.c +++ b/src/mod/applications/mod_dptools/mod_dptools.c @@ -1485,6 +1485,8 @@ SWITCH_STANDARD_APP(ivr_application_function) } else { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Unable to find menu\n"); } + } else { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No menus configured\n"); } switch_xml_free(cxml); } else { From 719416f66b1757d33364b6ffb37119e29596a5ae Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Mon, 10 Jan 2011 09:39:46 -0600 Subject: [PATCH 12/29] mem leak --- src/mod/xml_int/mod_xml_rpc/mod_xml_rpc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mod/xml_int/mod_xml_rpc/mod_xml_rpc.c b/src/mod/xml_int/mod_xml_rpc/mod_xml_rpc.c index be06b148cd..468190d887 100644 --- a/src/mod/xml_int/mod_xml_rpc/mod_xml_rpc.c +++ b/src/mod/xml_int/mod_xml_rpc/mod_xml_rpc.c @@ -744,6 +744,7 @@ abyss_bool handler_hook(TSession * r) if (dateValue) { ResponseAddField(r, "Date", dateValue); + free(dateValue); } } From 83ce26b226416b20416eeff70aaabade876920b8 Mon Sep 17 00:00:00 2001 From: Brian West Date: Mon, 10 Jan 2011 09:55:56 -0600 Subject: [PATCH 13/29] FS-2972 --- src/mod/applications/mod_voicemail/mod_voicemail.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/mod/applications/mod_voicemail/mod_voicemail.c b/src/mod/applications/mod_voicemail/mod_voicemail.c index 69dd217ca2..851ec77c61 100644 --- a/src/mod/applications/mod_voicemail/mod_voicemail.c +++ b/src/mod/applications/mod_voicemail/mod_voicemail.c @@ -2337,6 +2337,7 @@ static switch_status_t deliver_vm(vm_profile_t *profile, const char *filename; switch_xml_t x_param, x_params; char *vm_email = NULL; + char *vm_email_from = NULL; char *vm_notify_email = NULL; char *email_addr = NULL; char *vm_timezone = NULL; @@ -2401,6 +2402,8 @@ static switch_status_t deliver_vm(vm_profile_t *profile, vm_email = switch_core_strdup(pool, val); } else if (!strcasecmp(var, "vm-notify-mailto")) { vm_notify_email = switch_core_strdup(pool, val); + } else if (!strcasecmp(var, "vm-mailfrom")) { + vm_email_from = switch_core_strdup(pool, val); } else if (!strcasecmp(var, "email-addr")) { email_addr = switch_core_strdup(pool, val); } else if (!strcasecmp(var, "vm-email-all-messages") && (send_main = switch_true(val))) { @@ -2544,7 +2547,9 @@ static switch_status_t deliver_vm(vm_profile_t *profile, switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "voicemail_message_len", duration_str); - if (zstr(profile->email_from)) { + if (!zstr(vm_email_from)) { + from = switch_core_strdup(pool, vm_email_from); + } else if (zstr(profile->email_from)) { from = switch_core_sprintf(pool, "%s@%s", myid, domain_name); } else { from = switch_event_expand_headers(params, profile->email_from); From a95a4eeee8910f87f0ea1156148834a56e4e6edf Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Mon, 10 Jan 2011 11:29:55 -0500 Subject: [PATCH 14/29] Freetdm: Added check for channel_on_routing called more than once on incoming calls --- libs/freetdm/src/ftdm_io.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index fb153c8062..f97029b8dc 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -2281,7 +2281,8 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_indicate(const char *file, const ch status = ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_BUSY, 1); break; case FTDM_CHANNEL_INDICATE_PROCEED: - if (!ftdm_test_flag(ftdmchan->span, FTDM_SPAN_USE_PROCEED_STATE)) { + if (!ftdm_test_flag(ftdmchan->span, FTDM_SPAN_USE_PROCEED_STATE) || + ftdmchan->state == FTDM_CHANNEL_STATE_PROCEED) { ftdm_ack_indication(ftdmchan, indication, status); goto done; } From 22ba5b35602df8b210732330ebe1cfdc7fa71002 Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Mon, 10 Jan 2011 12:03:49 -0500 Subject: [PATCH 15/29] freetdm : Progress indicator not sent by default on outgoing calls --- .../src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 1591fb2a0e..9b4b7872c4 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 @@ -39,7 +39,7 @@ void sngisdn_snd_setup(ftdm_channel_t *ftdmchan) ConEvnt conEvnt; sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data; sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; - ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_ORIG_NISDN}; + ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_INVALID}; ftdm_assert((!sngisdn_info->suInstId && !sngisdn_info->spInstId), "Trying to call out, but call data was not cleared\n"); From 29daaa07b0cdab12ce856c7520cde5270c68effc Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 10 Jan 2011 11:27:26 -0600 Subject: [PATCH 16/29] FS-2960 --- src/include/switch_odbc.h | 3 + src/switch_odbc.c | 114 +++++++++++++++++++++++++++----------- 2 files changed, 84 insertions(+), 33 deletions(-) diff --git a/src/include/switch_odbc.h b/src/include/switch_odbc.h index f76384003a..103fe0f0d7 100644 --- a/src/include/switch_odbc.h +++ b/src/include/switch_odbc.h @@ -34,6 +34,8 @@ #include +#define DEFAULT_ODBC_RETRIES 120 + SWITCH_BEGIN_EXTERN_C struct switch_odbc_handle; typedef void *switch_odbc_statement_handle_t; @@ -50,6 +52,7 @@ typedef enum { } switch_odbc_status_t; SWITCH_DECLARE(switch_odbc_handle_t *) switch_odbc_handle_new(const char *dsn, const char *username, const char *password); +SWITCH_DECLARE(void) switch_odbc_set_num_retries(switch_odbc_handle_t *handle, int num_retries); SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_disconnect(switch_odbc_handle_t *handle); SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_connect(switch_odbc_handle_t *handle); SWITCH_DECLARE(void) switch_odbc_handle_destroy(switch_odbc_handle_t **handlep); diff --git a/src/switch_odbc.c b/src/switch_odbc.c index 48ba62ce03..a7c2153304 100644 --- a/src/switch_odbc.c +++ b/src/switch_odbc.c @@ -57,6 +57,7 @@ struct switch_odbc_handle { char odbc_driver[256]; BOOL is_firebird; int affected_rows; + int num_retries; }; #endif @@ -90,6 +91,7 @@ SWITCH_DECLARE(switch_odbc_handle_t *) switch_odbc_handle_new(const char *dsn, c new_handle->env = SQL_NULL_HANDLE; new_handle->state = SWITCH_ODBC_STATE_INIT; new_handle->affected_rows = 0; + new_handle->num_retries = DEFAULT_ODBC_RETRIES; return new_handle; @@ -104,6 +106,15 @@ SWITCH_DECLARE(switch_odbc_handle_t *) switch_odbc_handle_new(const char *dsn, c return NULL; } +SWITCH_DECLARE(void) switch_odbc_set_num_retries(switch_odbc_handle_t *handle, int num_retries) +{ +#ifdef SWITCH_HAVE_ODBC + if (handle) { + handle->num_retries = num_retries; + } +#endif +} + SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_disconnect(switch_odbc_handle_t *handle) { #ifdef SWITCH_HAVE_ODBC @@ -133,6 +144,53 @@ SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_disconnect(switch_odbc_h #ifdef SWITCH_HAVE_ODBC +static switch_odbc_status_t init_odbc_handles(switch_odbc_handle_t *handle, switch_bool_t do_reinit) +{ + int result; + + if (!handle) { + return SWITCH_ODBC_FAIL; + } + + /* if handle is already initialized, and we're supposed to reinit - free old handle first */ + if (do_reinit == SWITCH_TRUE && handle->env != SQL_NULL_HANDLE) { + SQLFreeHandle(SQL_HANDLE_DBC, handle->con); + SQLFreeHandle(SQL_HANDLE_ENV, handle->env); + handle->env = SQL_NULL_HANDLE; + } + + if (handle->env == SQL_NULL_HANDLE) { + result = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &handle->env); + + if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error AllocHandle\n"); + handle->env = SQL_NULL_HANDLE; /* Reset handle value, just in case */ + return SWITCH_ODBC_FAIL; + } + + result = SQLSetEnvAttr(handle->env, SQL_ATTR_ODBC_VERSION, (void *) SQL_OV_ODBC3, 0); + + if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error SetEnv\n"); + SQLFreeHandle(SQL_HANDLE_ENV, handle->env); + handle->env = SQL_NULL_HANDLE; /* Reset handle value after it's freed */ + return SWITCH_ODBC_FAIL; + } + + result = SQLAllocHandle(SQL_HANDLE_DBC, handle->env, &handle->con); + + if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error AllocHDB %d\n", result); + SQLFreeHandle(SQL_HANDLE_ENV, handle->env); + handle->env = SQL_NULL_HANDLE; /* Reset handle value after it's freed */ + return SWITCH_ODBC_FAIL; + } + SQLSetConnectAttr(handle->con, SQL_LOGIN_TIMEOUT, (SQLPOINTER *) 10, 0); + } + + return SWITCH_ODBC_SUCCESS; +} + static int db_is_up(switch_odbc_handle_t *handle) { int ret = 0; @@ -143,12 +201,18 @@ static int db_is_up(switch_odbc_handle_t *handle) switch_odbc_status_t recon = 0; char *err_str = NULL; SQLCHAR sql[255] = ""; - int max_tries = 120; + int max_tries = DEFAULT_ODBC_RETRIES; int code = 0; SQLRETURN rc; SQLSMALLINT nresultcols; + if (handle) { + max_tries = handle->num_retries; + if (max_tries < 1) + max_tries = DEFAULT_ODBC_RETRIES; + } + top: if (!handle) { @@ -199,6 +263,13 @@ static int db_is_up(switch_odbc_handle_t *handle) error: err_str = switch_odbc_handle_get_error(handle, stmt); + + /* Make sure to free the handle before we try to reconnect */ + if (stmt) { + SQLFreeHandle(SQL_HANDLE_STMT, stmt); + stmt = NULL; + } + recon = switch_odbc_handle_connect(handle); max_tries--; @@ -228,11 +299,6 @@ static int db_is_up(switch_odbc_handle_t *handle) goto done; } - if (stmt) { - SQLFreeHandle(SQL_HANDLE_STMT, stmt); - stmt = NULL; - } - switch_safe_free(err_str); switch_yield(1000000); goto top; @@ -274,31 +340,8 @@ SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_connect(switch_odbc_hand SQLSMALLINT valueLength = 0; int i = 0; - if (handle->env == SQL_NULL_HANDLE) { - result = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &handle->env); + init_odbc_handles(handle, SWITCH_FALSE); /* Init ODBC handles, if they are already initialized, don't do it again */ - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error AllocHandle\n"); - return SWITCH_ODBC_FAIL; - } - - result = SQLSetEnvAttr(handle->env, SQL_ATTR_ODBC_VERSION, (void *) SQL_OV_ODBC3, 0); - - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error SetEnv\n"); - SQLFreeHandle(SQL_HANDLE_ENV, handle->env); - return SWITCH_ODBC_FAIL; - } - - result = SQLAllocHandle(SQL_HANDLE_DBC, handle->env, &handle->con); - - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error AllocHDB %d\n", result); - SQLFreeHandle(SQL_HANDLE_ENV, handle->env); - return SWITCH_ODBC_FAIL; - } - SQLSetConnectAttr(handle->con, SQL_LOGIN_TIMEOUT, (SQLPOINTER *) 10, 0); - } if (handle->state == SWITCH_ODBC_STATE_CONNECTED) { switch_odbc_handle_disconnect(handle); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Re-connecting %s\n", handle->dsn); @@ -325,7 +368,9 @@ SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_connect(switch_odbc_hand SQLGetDiagRec(SQL_HANDLE_DBC, handle->con, 1, stat, &err, msg, 100, &mlen); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error SQLConnect=%d errno=%d %s\n", result, (int) err, msg); } - SQLFreeHandle(SQL_HANDLE_ENV, handle->env); + + /* Deallocate handles again, more chanses to succeed when reconnecting */ + init_odbc_handles(handle, SWITCH_TRUE); /* Reinit ODBC handles */ return SWITCH_ODBC_FAIL; } @@ -554,6 +599,7 @@ SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_callback_exec_detailed(c } SQLFreeHandle(SQL_HANDLE_STMT, stmt); + stmt = NULL; /* Make sure we don't try to free this handle again */ if (!err_cnt) { return SWITCH_ODBC_SUCCESS; @@ -593,8 +639,10 @@ SWITCH_DECLARE(void) switch_odbc_handle_destroy(switch_odbc_handle_t **handlep) if (handle) { switch_odbc_handle_disconnect(handle); - SQLFreeHandle(SQL_HANDLE_DBC, handle->con); - SQLFreeHandle(SQL_HANDLE_ENV, handle->env); + if (handle->env != SQL_NULL_HANDLE) { + SQLFreeHandle(SQL_HANDLE_DBC, handle->con); + SQLFreeHandle(SQL_HANDLE_ENV, handle->env); + } switch_safe_free(handle->dsn); switch_safe_free(handle->username); switch_safe_free(handle->password); From a9366e4485c2990c394e86d9de3a9c9e098e4aba Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 10 Jan 2011 13:20:38 -0600 Subject: [PATCH 17/29] doh --- src/switch_rtp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/switch_rtp.c b/src/switch_rtp.c index 04d5940167..038e1d981b 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -2968,7 +2968,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_ } - if (rtp_session->dtmf_data.in_digit_ts) { + if (bytes && rtp_session->dtmf_data.in_digit_ts) { if (!switch_rtp_ready(rtp_session)) { goto end; } From e42c423c9275ec5aec8499c4035978087fc84c02 Mon Sep 17 00:00:00 2001 From: Brian West Date: Mon, 10 Jan 2011 14:44:54 -0600 Subject: [PATCH 18/29] add tab completion stuffs --- libs/freetdm/mod_freetdm/mod_freetdm.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index f50d26c290..778c5f403f 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -4177,6 +4177,19 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_freetdm_load) freetdm_endpoint_interface->state_handler = &freetdm_state_handlers; SWITCH_ADD_API(commands_api_interface, "ftdm", "FreeTDM commands", ft_function, FT_SYNTAX); + switch_console_set_complete("add ftdm start"); + switch_console_set_complete("add ftdm stop"); + switch_console_set_complete("add ftdm retart"); + switch_console_set_complete("add ftdm dump"); + switch_console_set_complete("add ftdm sigstatus get"); + switch_console_set_complete("add ftdm sigstatus set"); + switch_console_set_complete("add ftdm trace"); + switch_console_set_complete("add ftdm notrace"); + switch_console_set_complete("add ftdm q931_pcap"); + switch_console_set_complete("add ftdm gains"); + switch_console_set_complete("add ftdm dtmf on"); + switch_console_set_complete("add ftdm dtmf off"); + SWITCH_ADD_APP(app_interface, "disable_ec", "Disable Echo Canceller", "Disable Echo Canceller", disable_ec_function, "", SAF_NONE); SWITCH_ADD_APP(app_interface, "disable_dtmf", "Disable DTMF Detection", "Disable DTMF Detection", disable_dtmf_function, "", SAF_NONE); From 21f8605d6871680e90a8eee76be1abb2a52e2761 Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Mon, 10 Jan 2011 16:42:47 -0500 Subject: [PATCH 19/29] freetdm: fix for enabling DTMF detection on d-channel --- libs/freetdm/src/ftdm_io.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index f97029b8dc..430b58a31e 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -2923,23 +2923,27 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_command(ftdm_channel_t *ftdmchan, ftdm_co case FTDM_COMMAND_ENABLE_DTMF_DETECT: { /* if they don't have thier own, use ours */ - if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_DTMF_DETECT)) { - teletone_dtmf_detect_init (&ftdmchan->dtmf_detect, ftdmchan->rate); - ftdm_set_flag(ftdmchan, FTDM_CHANNEL_DTMF_DETECT); - ftdm_set_flag(ftdmchan, FTDM_CHANNEL_SUPRESS_DTMF); - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Enabled software DTMF detector\n"); - GOTO_STATUS(done, FTDM_SUCCESS); + if (FTDM_IS_VOICE_CHANNEL(ftdmchan)) { + if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_DTMF_DETECT)) { + teletone_dtmf_detect_init (&ftdmchan->dtmf_detect, ftdmchan->rate); + ftdm_set_flag(ftdmchan, FTDM_CHANNEL_DTMF_DETECT); + ftdm_set_flag(ftdmchan, FTDM_CHANNEL_SUPRESS_DTMF); + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Enabled software DTMF detector\n"); + GOTO_STATUS(done, FTDM_SUCCESS); + } } } break; case FTDM_COMMAND_DISABLE_DTMF_DETECT: { - if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_DTMF_DETECT)) { - teletone_dtmf_detect_init (&ftdmchan->dtmf_detect, ftdmchan->rate); - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_DTMF_DETECT); - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_SUPRESS_DTMF); - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Disabled software DTMF detector\n"); - GOTO_STATUS(done, FTDM_SUCCESS); + if (FTDM_IS_VOICE_CHANNEL(ftdmchan)) { + if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_DTMF_DETECT)) { + teletone_dtmf_detect_init (&ftdmchan->dtmf_detect, ftdmchan->rate); + ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_DTMF_DETECT); + ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_SUPRESS_DTMF); + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Disabled software DTMF detector\n"); + GOTO_STATUS(done, FTDM_SUCCESS); + } } } break; From 62941f69d8d3f32856e136e49eff7f5c5f4135bd Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Mon, 10 Jan 2011 17:46:18 -0500 Subject: [PATCH 20/29] Added FTDM_SPAN_NON_STOPPABLE flag for signalling modules that do not support individual start/stop --- libs/freetdm/src/ftdm_io.c | 9 +++++++++ .../src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c | 1 + libs/freetdm/src/include/private/ftdm_types.h | 3 +++ 3 files changed, 13 insertions(+) diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 430b58a31e..5e49fda520 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -634,6 +634,10 @@ static ftdm_status_t ftdm_span_destroy(ftdm_span_t *span) ftdm_mutex_lock(span->mutex); /* stop the signaling */ + + /* This is a forced stopped */ + ftdm_clear_flag(span, FTDM_SPAN_NON_STOPPABLE); + ftdm_span_stop(span); /* destroy the channels */ @@ -739,6 +743,11 @@ FT_DECLARE(ftdm_status_t) ftdm_span_stop(ftdm_span_t *span) ftdm_status_t status = FTDM_SUCCESS; ftdm_mutex_lock(span->mutex); + + if (ftdm_test_flag(span, FTDM_SPAN_NON_STOPPABLE)) { + status = FTDM_NOTIMPL; + goto done; + } if (!ftdm_test_flag(span, FTDM_SPAN_STARTED)) { status = FTDM_EINVAL; 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 c13f584df8..97650245a1 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 @@ -1094,6 +1094,7 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_isdn_span_config) ftdm_set_flag(span, FTDM_SPAN_USE_SIGNALS_QUEUE); ftdm_set_flag(span, FTDM_SPAN_USE_PROCEED_STATE); ftdm_set_flag(span, FTDM_SPAN_USE_SKIP_STATES); + ftdm_set_flag(span, FTDM_SPAN_NON_STOPPABLE); if (span->trunk_type == FTDM_TRUNK_BRI_PTMP || span->trunk_type == FTDM_TRUNK_BRI) { diff --git a/libs/freetdm/src/include/private/ftdm_types.h b/libs/freetdm/src/include/private/ftdm_types.h index d79835733b..3bc986d7f6 100644 --- a/libs/freetdm/src/include/private/ftdm_types.h +++ b/libs/freetdm/src/include/private/ftdm_types.h @@ -186,6 +186,9 @@ typedef enum { /* If this flag is set, the signalling module supports jumping directly to state up, without going through PROGRESS/PROGRESS_MEDIA */ FTDM_SPAN_USE_SKIP_STATES = (1 << 12), + /* If this flag is set, then this span cannot be stopped individually, it can only be stopped + on freetdm unload */ + FTDM_SPAN_NON_STOPPABLE = (1 << 13), } ftdm_span_flag_t; /*! \brief Channel supported features */ From fcc912a991a9513cc605ea0f3a24f96c2c4ccdfd Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 10 Jan 2011 17:26:14 -0600 Subject: [PATCH 21/29] add mod_fsk --- src/mod/applications/mod_fsk/Makefile | 6 + src/mod/applications/mod_fsk/fsk.c | 351 ++++++++++++++ src/mod/applications/mod_fsk/fsk.h | 113 +++++ src/mod/applications/mod_fsk/fsk_callerid.c | 398 ++++++++++++++++ src/mod/applications/mod_fsk/fsk_callerid.h | 144 ++++++ src/mod/applications/mod_fsk/mod_fsk.c | 486 ++++++++++++++++++++ src/mod/applications/mod_fsk/uart.c | 124 +++++ src/mod/applications/mod_fsk/uart.h | 76 +++ 8 files changed, 1698 insertions(+) create mode 100644 src/mod/applications/mod_fsk/Makefile create mode 100644 src/mod/applications/mod_fsk/fsk.c create mode 100644 src/mod/applications/mod_fsk/fsk.h create mode 100644 src/mod/applications/mod_fsk/fsk_callerid.c create mode 100644 src/mod/applications/mod_fsk/fsk_callerid.h create mode 100644 src/mod/applications/mod_fsk/mod_fsk.c create mode 100644 src/mod/applications/mod_fsk/uart.c create mode 100644 src/mod/applications/mod_fsk/uart.h diff --git a/src/mod/applications/mod_fsk/Makefile b/src/mod/applications/mod_fsk/Makefile new file mode 100644 index 0000000000..620f3f751c --- /dev/null +++ b/src/mod/applications/mod_fsk/Makefile @@ -0,0 +1,6 @@ +BASE=../../../.. + +LOCAL_SOURCES=fsk.c uart.c fsk_callerid.c +LOCAL_OBJS=fsk.o uart.o fsk_callerid.o +include $(BASE)/build/modmake.rules + diff --git a/src/mod/applications/mod_fsk/fsk.c b/src/mod/applications/mod_fsk/fsk.c new file mode 100644 index 0000000000..773b0deaae --- /dev/null +++ b/src/mod/applications/mod_fsk/fsk.c @@ -0,0 +1,351 @@ + +/* + * bell202.c + * + * Copyright (c) 2005 Robert Krten. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This module contains a Bell-202 1200-baud FSK decoder, suitable for + * use in a library. The general style of the library calls is modeled + * after the POSIX pthread_*() functions. + * + * 2005 03 20 R. Krten created +*/ + +#include +#include +#include +#include +#include + +#include "fsk.h" +#include "uart.h" + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +fsk_modem_definition_t fsk_modem_definitions[] = +{ + { /* FSK_V23_FORWARD_MODE1 */ 1700, 1300, 600 }, + { /* FSK_V23_FORWARD_MODE2 */ 2100, 1300, 1200 }, + { /* FSK_V23_BACKWARD */ 450, 390, 75 }, + { /* FSK_BELL202 */ 2200, 1200, 1200 }, +}; + +/* + * dsp_fsk_attr_init + * + * Initializes the attributes structure; this must be done before the + * attributes structure is used. +*/ + +void dsp_fsk_attr_init (dsp_fsk_attr_t *attr) +{ + memset(attr, 0, sizeof(*attr)); +} + +/* + * dsp_fsk_attr_get_bithandler + * dsp_fsk_attr_set_bithandler + * dsp_fsk_attr_get_bytehandler + * dsp_fsk_attr_set_bytehandler + * dsp_fsk_attr_getsamplerate + * dsp_fsk_attr_setsamplerate + * + * These functions get and set their respective elements from the + * attributes structure. If an error code is returned, it is just + * zero == ok, -1 == fail. +*/ + +bithandler_func_t dsp_fsk_attr_get_bithandler(dsp_fsk_attr_t *attr, void **bithandler_arg) +{ + *bithandler_arg = attr->bithandler_arg; + return attr->bithandler; +} + +void dsp_fsk_attr_set_bithandler(dsp_fsk_attr_t *attr, bithandler_func_t bithandler, void *bithandler_arg) +{ + attr->bithandler = bithandler; + attr->bithandler_arg = bithandler_arg; +} + +bytehandler_func_t dsp_fsk_attr_get_bytehandler(dsp_fsk_attr_t *attr, void **bytehandler_arg) +{ + *bytehandler_arg = attr->bytehandler_arg; + return attr->bytehandler; +} + +void dsp_fsk_attr_set_bytehandler(dsp_fsk_attr_t *attr, bytehandler_func_t bytehandler, void *bytehandler_arg) +{ + attr->bytehandler = bytehandler; + attr->bytehandler_arg = bytehandler_arg; +} + +int dsp_fsk_attr_get_samplerate (dsp_fsk_attr_t *attr) +{ + return attr->sample_rate; +} + +int dsp_fsk_attr_set_samplerate (dsp_fsk_attr_t *attr, int samplerate) +{ + if (samplerate <= 0) { + return -1; + } + attr->sample_rate = samplerate; + return 0; +} + +/* + * dsp_fsk_create + * + * Creates a handle for subsequent use. The handle is created to contain + * a context data structure for use by the sample handler function. The + * function expects an initialized attributes structure, and returns the + * handle or a NULL if there were errors. + * + * Once created, the handle can be used until it is destroyed. +*/ + +dsp_fsk_handle_t *dsp_fsk_create(dsp_fsk_attr_t *attr) +{ + int i; + double phi_mark, phi_space; + dsp_fsk_handle_t *handle; + + handle = malloc(sizeof(*handle)); + if (!handle) { + return NULL; + } + + memset(handle, 0, sizeof(*handle)); + + /* fill the attributes member */ + memcpy(&handle->attr, attr, sizeof(*attr)); + + /* see if we can do downsampling. We only really need 6 samples to "match" */ + if (attr->sample_rate / fsk_modem_definitions[FSK_BELL202].freq_mark > 6) { + handle->downsampling_count = attr->sample_rate / fsk_modem_definitions[FSK_BELL202].freq_mark / 6; + } else { + handle->downsampling_count = 1; + } + handle->current_downsample = 1; + + /* calculate the correlate size (number of samples required for slowest wave) */ + handle->corrsize = attr->sample_rate / handle->downsampling_count / fsk_modem_definitions[FSK_BELL202].freq_mark; + + /* allocate the correlation sin/cos arrays and initialize */ + for (i = 0; i < 4; i++) { + handle->correlates[i] = malloc(sizeof(double) * handle->corrsize); + if (handle->correlates[i] == NULL) { + /* some failed, back out memory allocations */ + dsp_fsk_destroy(&handle); + return NULL; + } + } + + /* now initialize them */ + phi_mark = 2. * M_PI / ((double) attr->sample_rate / (double) handle->downsampling_count / (double) fsk_modem_definitions[FSK_BELL202].freq_mark); + phi_space = 2. * M_PI / ((double) attr->sample_rate / (double) handle->downsampling_count / (double) fsk_modem_definitions[FSK_BELL202].freq_space); + + for (i = 0; i < handle->corrsize; i++) { + handle->correlates[0][i] = sin(phi_mark * (double) i); + handle->correlates[1][i] = cos(phi_mark * (double) i); + handle->correlates[2][i] = sin(phi_space * (double) i); + handle->correlates[3][i] = cos(phi_space * (double) i); + } + + /* initialize the ring buffer */ + handle->buffer = malloc(sizeof(double) * handle->corrsize); + if (!handle->buffer) { /* failed; back out memory allocations */ + dsp_fsk_destroy(&handle); + return NULL; + } + memset(handle->buffer, 0, sizeof(double) * handle->corrsize); + handle->ringstart = 0; + + /* initalize intra-cell position */ + handle->cellpos = 0; + handle->celladj = fsk_modem_definitions[FSK_BELL202].baud_rate / (double) attr->sample_rate * (double) handle->downsampling_count; + + /* if they have provided a byte handler, add a UART to the processing chain */ + if (handle->attr.bytehandler) { + dsp_uart_attr_t uart_attr; + dsp_uart_handle_t *uart_handle; + + dsp_uart_attr_init(&uart_attr); + dsp_uart_attr_set_bytehandler(&uart_attr, handle->attr.bytehandler, handle->attr.bytehandler_arg); + uart_handle = dsp_uart_create(&uart_attr); + if (uart_handle == NULL) { + dsp_fsk_destroy(&handle); + return NULL; + } + handle->attr.bithandler = dsp_uart_bit_handler; + handle->attr.bithandler_arg = uart_handle; + } + + return handle; +} + +/* + * dsp_fsk_destroy + * + * Destroys a handle, releasing any associated memory. Sets handle pointer to NULL + * so A destroyed handle can not be used for anything after the destroy. +*/ + +void dsp_fsk_destroy(dsp_fsk_handle_t **handle) +{ + int i; + + /* if empty handle, just return */ + if (*handle == NULL) { + return; + } + + for (i = 0; i < 4; i++) { + if ((*handle)->correlates[i] != NULL) { + free((*handle)->correlates[i]); + (*handle)->correlates[i] = NULL; + } + } + + if ((*handle)->buffer != NULL) { + free((*handle)->buffer); + (*handle)->buffer = NULL; + } + + if ((*handle)->attr.bytehandler) { + dsp_uart_handle_t** dhandle = (void *)(&(*handle)->attr.bithandler_arg); + dsp_uart_destroy(dhandle); + } + + free(*handle); + *handle = NULL; +} + +/* + * dsp_fsk_sample + * + * This is the main processing entry point. The function accepts a normalized + * sample (i.e., one whose range is between -1 and +1). The function performs + * the Bell-202 FSK modem decode processing, and, if it detects a valid bit, + * will call the bithandler associated with the attributes structure. + * + * For the Bell-202 standard, a logical zero (space) is 2200 Hz, and a logical + * one (mark) is 1200 Hz. +*/ + +void +dsp_fsk_sample (dsp_fsk_handle_t *handle, double normalized_sample) +{ + double val; + double factors[4]; + int i, j; + + /* if we can avoid processing samples, do so */ + if (handle->downsampling_count != 1) { + if (handle->current_downsample < handle->downsampling_count) { + handle->current_downsample++; + return; /* throw this sample out */ + } + handle->current_downsample = 1; + } + + /* store sample in buffer */ + handle->buffer[handle->ringstart++] = normalized_sample; + if (handle->ringstart >= handle->corrsize) { + handle->ringstart = 0; + } + + /* do the correlation calculation */ + factors[0] = factors[1] = factors[2] = factors[3] = 0; /* clear out intermediate sums */ + j = handle->ringstart; + for (i = 0; i < handle->corrsize; i++) { + if (j >= handle->corrsize) { + j = 0; + } + val = handle->buffer[j]; + factors[0] += handle->correlates[0][i] * val; + factors[1] += handle->correlates[1][i] * val; + factors[2] += handle->correlates[2][i] * val; + factors[3] += handle->correlates[3][i] * val; + j++; + } + + /* store the bit (bit value is comparison of the two sets of correlate factors) */ + handle->previous_bit = handle->current_bit; + handle->current_bit = (factors[0] * factors[0] + factors[1] * factors[1] > factors[2] * factors[2] + factors[3] * factors[3]); + + /* if there's a transition, we can synchronize the cell position */ + if (handle->previous_bit != handle->current_bit) { + handle->cellpos = 0.5; /* adjust cell position to be in the middle of the cell */ + } + handle->cellpos += handle->celladj; /* walk the cell along */ + + if (handle->cellpos > 1.0) { + handle->cellpos -= 1.0; + + switch (handle->state) { + case FSK_STATE_DATA: + { + + (*handle->attr.bithandler) (handle->attr.bithandler_arg, handle->current_bit); + } + break; + case FSK_STATE_CHANSEIZE: + { + + if (handle->last_bit != handle->current_bit) { + handle->conscutive_state_bits++; + } else { + handle->conscutive_state_bits = 0; + } + + if (handle->conscutive_state_bits > 15) { + handle->state = FSK_STATE_CARRIERSIG; + handle->conscutive_state_bits = 0; + } + } + break; + case FSK_STATE_CARRIERSIG: + { + if (handle->current_bit) { + handle->conscutive_state_bits++; + } else { + handle->conscutive_state_bits = 0; + } + + if (handle->conscutive_state_bits > 15) { + handle->state = FSK_STATE_DATA; + handle->conscutive_state_bits = 0; + } + } + break; + } + + handle->last_bit = handle->current_bit; + } +} + diff --git a/src/mod/applications/mod_fsk/fsk.h b/src/mod/applications/mod_fsk/fsk.h new file mode 100644 index 0000000000..b098444d03 --- /dev/null +++ b/src/mod/applications/mod_fsk/fsk.h @@ -0,0 +1,113 @@ +/* + * bell202.h + * + * Copyright (c) 2005 Robert Krten. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This module contains the manifest constants and declarations for + * the Bell-202 1200 baud FSK modem. + * + * 2005 03 20 R. Krten created +*/ + +#ifndef __FSK_H__ +#define __FSK_H__ +#include "uart.h" + +typedef struct { + int freq_space; /* Frequency of the 0 bit */ + int freq_mark; /* Frequency of the 1 bit */ + int baud_rate; /* baud rate for the modem */ +} fsk_modem_definition_t; + +/* Must be kept in sync with fsk_modem_definitions array in fsk.c */ +/* V.23 definitions: http://www.itu.int/rec/recommendation.asp?type=folders&lang=e&parent=T-REC-V.23 */ +typedef enum { + FSK_V23_FORWARD_MODE1 = 0, /* Maximum 600 bps for long haul */ + FSK_V23_FORWARD_MODE2, /* Standard 1200 bps V.23 */ + FSK_V23_BACKWARD, /* 75 bps return path for V.23 */ + FSK_BELL202 /* Bell 202 half-duplex 1200 bps */ +} fsk_modem_types_t; + +typedef enum { + FSK_STATE_CHANSEIZE = 0, + FSK_STATE_CARRIERSIG, + FSK_STATE_DATA +} fsk_state_t; + +typedef struct dsp_fsk_attr_s +{ + int sample_rate; /* sample rate in HZ */ + bithandler_func_t bithandler; /* bit handler */ + void *bithandler_arg; /* arbitrary ID passed to bithandler as first argument */ + bytehandler_func_t bytehandler; /* byte handler */ + void *bytehandler_arg; /* arbitrary ID passed to bytehandler as first argument */ +} dsp_fsk_attr_t; + +typedef struct +{ + fsk_state_t state; + dsp_fsk_attr_t attr; /* attributes structure */ + double *correlates[4]; /* one for each of sin/cos for mark/space */ + int corrsize; /* correlate size (also number of samples in ring buffer) */ + double *buffer; /* sample ring buffer */ + int ringstart; /* ring buffer start offset */ + double cellpos; /* bit cell position */ + double celladj; /* bit cell adjustment for each sample */ + int previous_bit; /* previous bit (for detecting a transition to sync-up cell position) */ + int current_bit; /* current bit */ + int last_bit; + int downsampling_count; /* number of samples to skip */ + int current_downsample; /* current skip count */ + int conscutive_state_bits; /* number of bits in a row that matches the pattern for the current state */ +} dsp_fsk_handle_t; + +/* + * Function prototypes + * + * General calling order is: + * a) create the attributes structure (dsp_fsk_attr_init) + * b) initialize fields in the attributes structure (dsp_fsk_attr_set_*) + * c) create a Bell-202 handle (dsp_fsk_create) + * d) feed samples through the handler (dsp_fsk_sample) +*/ + +void dsp_fsk_attr_init(dsp_fsk_attr_t *attributes); + +bithandler_func_t dsp_fsk_attr_get_bithandler(dsp_fsk_attr_t *attributes, void **bithandler_arg); +void dsp_fsk_attr_set_bithandler(dsp_fsk_attr_t *attributes, bithandler_func_t bithandler, void *bithandler_arg); +bytehandler_func_t dsp_fsk_attr_get_bytehandler(dsp_fsk_attr_t *attributes, void **bytehandler_arg); +void dsp_fsk_attr_set_bytehandler(dsp_fsk_attr_t *attributes, bytehandler_func_t bytehandler, void *bytehandler_arg); +int dsp_fsk_attr_get_samplerate(dsp_fsk_attr_t *attributes); +int dsp_fsk_attr_set_samplerate(dsp_fsk_attr_t *attributes, int samplerate); + +dsp_fsk_handle_t * dsp_fsk_create(dsp_fsk_attr_t *attributes); +void dsp_fsk_destroy(dsp_fsk_handle_t **handle); + +void dsp_fsk_sample(dsp_fsk_handle_t *handle, double normalized_sample); + +extern fsk_modem_definition_t fsk_modem_definitions[]; + +#endif + diff --git a/src/mod/applications/mod_fsk/fsk_callerid.c b/src/mod/applications/mod_fsk/fsk_callerid.c new file mode 100644 index 0000000000..2146f663c5 --- /dev/null +++ b/src/mod/applications/mod_fsk/fsk_callerid.c @@ -0,0 +1,398 @@ +/* + * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * Copyright (C) 2005-2011, 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 + * + * mod_fsk -- FSK data transfer + * + */ + +#include "switch.h" +#include "fsk_callerid.h" + +void bitstream_init(bitstream_t *bsp, uint8_t *data, uint32_t datalen, endian_t endian, uint8_t ss) +{ + memset(bsp, 0, sizeof(*bsp)); + bsp->data = data; + bsp->datalen = datalen; + bsp->endian = endian; + bsp->ss = ss; + + if (endian < 0) { + bsp->top = bsp->bit_index = 7; + bsp->bot = 0; + } else { + bsp->top = bsp->bit_index = 0; + bsp->bot = 7; + } + +} + +int8_t bitstream_get_bit(bitstream_t *bsp) +{ + int8_t bit = -1; + + + if (bsp->byte_index >= bsp->datalen) { + goto done; + } + + if (bsp->ss) { + if (!bsp->ssv) { + bsp->ssv = 1; + return 0; + } else if (bsp->ssv == 2) { + bsp->byte_index++; + bsp->ssv = 0; + return 1; + } + } + + bit = (bsp->data[bsp->byte_index] >> (bsp->bit_index)) & 1; + + if (bsp->bit_index == bsp->bot) { + bsp->bit_index = bsp->top; + if (bsp->ss) { + bsp->ssv = 2; + goto done; + } + + if (++bsp->byte_index > bsp->datalen) { + bit = -1; + goto done; + } + + } else { + bsp->bit_index = bsp->bit_index + bsp->endian; + } + + + done: + return bit; +} + + + +static void fsk_byte_handler (void *x, int data) +{ + fsk_data_state_t *state = (fsk_data_state_t *) x; + uint8_t byte = (uint8_t)data; + + top: + + if (state->init == 3) { + return; + } + + if (state->dlen) { + goto add_byte; + } + + if (state->bpos == 1) { + state->blen = byte; + + if ((uint32_t)(state->dlen = state->bpos + byte + 2) > state->bufsize) { + state->dlen = state->bufsize; + } + goto top; + } + + add_byte: + + if (state->bpos <= state->dlen) { + state->buf[state->bpos++] = byte; + } else { + state->init = 3; + } +} + +switch_status_t fsk_data_init(fsk_data_state_t *state, uint8_t *data, uint32_t datalen) +{ + memset(state, 0, sizeof(*state)); + state->buf = data; + state->bufsize = datalen; + state->bpos = 2; + + return SWITCH_STATUS_SUCCESS; +} + +switch_status_t fsk_data_add_sdmf(fsk_data_state_t *state, const char *date, char *number) +{ + size_t dlen = strlen(date); + size_t nlen = strlen(number); + + state->buf[0] = CID_TYPE_SDMF; + memcpy(&state->buf[state->bpos], date, dlen); + state->bpos += dlen; + memcpy(&state->buf[state->bpos], number, nlen); + state->bpos += nlen; + + return SWITCH_STATUS_SUCCESS; +} + +switch_status_t fsk_data_add_mdmf(fsk_data_state_t *state, mdmf_type_t type, const uint8_t *data, uint32_t datalen) +{ + state->buf[0] = CID_TYPE_MDMF; + state->buf[state->bpos++] = type; + state->buf[state->bpos++] = (uint8_t)datalen; + memcpy(&state->buf[state->bpos], data, datalen); + state->bpos += datalen; + return SWITCH_STATUS_SUCCESS; +} + + +switch_status_t fsk_data_add_checksum(fsk_data_state_t *state) +{ + uint32_t i; + uint8_t check = 0; + + state->buf[1] = (uint8_t)(state->bpos - 2); + + for (i = 0; i < state->bpos; i++) { + check = check + state->buf[i]; + } + + state->checksum = state->buf[state->bpos] = (uint8_t)(256 - check); + state->bpos++; + + state->dlen = state->bpos; + state->blen = state->buf[1]; + + return SWITCH_STATUS_SUCCESS; +} + + +switch_status_t fsk_data_parse(fsk_data_state_t *state, size_t *type, char **data, size_t *len) +{ + + size_t i; + int sum = 0; + + top: + + if (state->checksum != 0 || state->ppos >= state->dlen - 1) { + return SWITCH_STATUS_FALSE; + } + + if (!state->ppos) { + for(i = 0; i < state->bpos; i++) { + sum += state->buf[i]; + } + state->checksum = sum % 256; + state->ppos = 2; + + if (state->buf[0] != CID_TYPE_MDMF && state->buf[0] != CID_TYPE_SDMF) { + state->checksum = -1; + } + goto top; + } + + if (state->buf[0] == CID_TYPE_SDMF) { + /* convert sdmf to mdmf so we don't need 2 parsers */ + if (state->ppos == 2) { + *type = MDMF_DATETIME; + *len = 8; + } else { + if (state->buf[state->ppos] == 'P' || state->buf[state->ppos] == 'O') { + *type = MDMF_NO_NUM; + *len = 1; + } else { + *type = MDMF_PHONE_NUM; + *len = state->blen - 8; + } + } + *data = (char *)&state->buf[state->ppos]; + state->ppos += *len; + return SWITCH_STATUS_SUCCESS; + } else if (state->buf[0] == CID_TYPE_MDMF) { + *type = state->buf[state->ppos++]; + *len = state->buf[state->ppos++]; + *data = (char *)&state->buf[state->ppos]; + state->ppos += *len; + return SWITCH_STATUS_SUCCESS; + } + + return SWITCH_STATUS_FALSE; +} + +switch_status_t fsk_demod_feed(fsk_data_state_t *state, int16_t *data, size_t samples) +{ + uint32_t x; + int16_t *sp = data; + + if (state->init == 3) { + return SWITCH_STATUS_FALSE; + } + + for (x = 0; x < samples; x++) { + dsp_fsk_sample (state->fsk1200_handle, (double) *sp++ / 32767.0); + if (state->dlen && state->bpos >= state->dlen) { + state->init = 3; + return SWITCH_STATUS_FALSE; + } + } + + return SWITCH_STATUS_SUCCESS; +} + +switch_status_t fsk_demod_destroy(fsk_data_state_t *state) +{ + dsp_fsk_destroy(&state->fsk1200_handle); + memset(state, 0, sizeof(*state)); + return SWITCH_STATUS_SUCCESS; +} + +int fsk_demod_init(fsk_data_state_t *state, int rate, uint8_t *buf, size_t bufsize) +{ + + dsp_fsk_attr_t fsk1200_attr; + + if (state->fsk1200_handle) { + dsp_fsk_destroy(&state->fsk1200_handle); + } + + memset(state, 0, sizeof(*state)); + memset(buf, 0, bufsize); + state->buf = buf; + state->bufsize = bufsize; + + dsp_fsk_attr_init (&fsk1200_attr); + dsp_fsk_attr_set_samplerate (&fsk1200_attr, rate); + dsp_fsk_attr_set_bytehandler (&fsk1200_attr, fsk_byte_handler, state); + state->fsk1200_handle = dsp_fsk_create (&fsk1200_attr); + + if (state->fsk1200_handle == NULL) { + return SWITCH_STATUS_FALSE; + } + + return SWITCH_STATUS_SUCCESS; +} + +size_t fsk_modulator_generate_bit(fsk_modulator_t *fsk_trans, int8_t bit, int16_t *buf, size_t buflen) +{ + size_t i; + + for(i = 0 ; i < buflen; i++) { + fsk_trans->bit_accum += fsk_trans->bit_factor; + if (fsk_trans->bit_accum >= FSK_MOD_FACTOR) { + fsk_trans->bit_accum -= (FSK_MOD_FACTOR + fsk_trans->bit_factor); + break; + } + + buf[i] = teletone_dds_state_modulate_sample(&fsk_trans->dds, bit); + } + + return i; +} + + +int32_t fsk_modulator_generate_carrier_bits(fsk_modulator_t *fsk_trans, uint32_t bits) +{ + uint32_t i = 0; + size_t r = 0; + int8_t bit = 1; + + for (i = 0; i < bits; i++) { + if ((r = fsk_modulator_generate_bit(fsk_trans, bit, fsk_trans->sample_buffer, sizeof(fsk_trans->sample_buffer) / 2))) { + if (fsk_trans->write_sample_callback(fsk_trans->sample_buffer, r, fsk_trans->user_data) != SWITCH_STATUS_SUCCESS) { + break; + } + } else { + break; + } + } + + return i; +} + + +void fsk_modulator_generate_chan_sieze(fsk_modulator_t *fsk_trans) +{ + uint32_t i = 0; + size_t r = 0; + int8_t bit = 0; + + for (i = 0; i < fsk_trans->chan_sieze_bits; i++) { + if ((r = fsk_modulator_generate_bit(fsk_trans, bit, fsk_trans->sample_buffer, sizeof(fsk_trans->sample_buffer) / 2))) { + if (fsk_trans->write_sample_callback(fsk_trans->sample_buffer, r, fsk_trans->user_data) != SWITCH_STATUS_SUCCESS) { + break; + } + } else { + break; + } + bit = !bit; + } + + +} + + +void fsk_modulator_send_data(fsk_modulator_t *fsk_trans) +{ + size_t r = 0; + int8_t bit = 0; + + while((bit = bitstream_get_bit(&fsk_trans->bs)) > -1) { + if ((r = fsk_modulator_generate_bit(fsk_trans, bit, fsk_trans->sample_buffer, sizeof(fsk_trans->sample_buffer) / 2))) { + if (fsk_trans->write_sample_callback(fsk_trans->sample_buffer, r, fsk_trans->user_data) != SWITCH_STATUS_SUCCESS) { + break; + } + } else { + break; + } + } +} + + +switch_status_t fsk_modulator_init(fsk_modulator_t *fsk_trans, + fsk_modem_types_t modem_type, + uint32_t sample_rate, + fsk_data_state_t *fsk_data, + float db_level, + uint32_t carrier_bits_start, + uint32_t carrier_bits_stop, + uint32_t chan_sieze_bits, + fsk_write_sample_t write_sample_callback, + void *user_data) +{ + memset(fsk_trans, 0, sizeof(*fsk_trans)); + fsk_trans->modem_type = modem_type; + teletone_dds_state_set_tone(&fsk_trans->dds, fsk_modem_definitions[fsk_trans->modem_type].freq_space, sample_rate, 0); + teletone_dds_state_set_tone(&fsk_trans->dds, fsk_modem_definitions[fsk_trans->modem_type].freq_mark, sample_rate, 1); + fsk_trans->bit_factor = (uint32_t)((fsk_modem_definitions[fsk_trans->modem_type].baud_rate * FSK_MOD_FACTOR) / (float)sample_rate); + fsk_trans->samples_per_bit = (uint32_t) (sample_rate / fsk_modem_definitions[fsk_trans->modem_type].baud_rate); + fsk_trans->est_bytes = (int32_t)(((fsk_data->dlen * 10) + carrier_bits_start + carrier_bits_stop + chan_sieze_bits) * ((fsk_trans->samples_per_bit + 1) * 2)); + fsk_trans->bit_accum = 0; + fsk_trans->fsk_data = fsk_data; + teletone_dds_state_set_tx_level(&fsk_trans->dds, db_level); + bitstream_init(&fsk_trans->bs, fsk_trans->fsk_data->buf, (uint32_t)fsk_trans->fsk_data->dlen, ENDIAN_BIG, 1); + fsk_trans->carrier_bits_start = carrier_bits_start; + fsk_trans->carrier_bits_stop = carrier_bits_stop; + fsk_trans->chan_sieze_bits = chan_sieze_bits; + fsk_trans->write_sample_callback = write_sample_callback; + fsk_trans->user_data = user_data; + return SWITCH_STATUS_SUCCESS; +} + diff --git a/src/mod/applications/mod_fsk/fsk_callerid.h b/src/mod/applications/mod_fsk/fsk_callerid.h new file mode 100644 index 0000000000..9018201ce5 --- /dev/null +++ b/src/mod/applications/mod_fsk/fsk_callerid.h @@ -0,0 +1,144 @@ +/* + * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * Copyright (C) 2005-2011, 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 + * + * mod_fsk -- FSK data transfer + * + */ +#ifndef __FSK_CALLER_ID_H +#define __FSK_CALLER_ID_H +SWITCH_BEGIN_EXTERN_C +#include "fsk.h" +#include "uart.h" + +#define FSK_MOD_FACTOR 0x10000 + +typedef enum { + ENDIAN_BIG = 1, + ENDIAN_LITTLE = -1 +} endian_t; + +typedef enum { + CID_TYPE_SDMF = 0x04, + CID_TYPE_MDMF = 0x80 +} cid_type_t; + +typedef enum { + MDMF_DATETIME = 1, + MDMF_PHONE_NUM = 2, + MDMF_DDN = 3, + MDMF_NO_NUM = 4, + MDMF_PHONE_NAME = 7, + MDMF_NO_NAME = 8, + MDMF_ALT_ROUTE = 9, + MDMF_NAME_VALUE = 10, + MDMF_INVALID = 11 +} mdmf_type_t; + +struct bitstream { + uint8_t *data; + uint32_t datalen; + uint32_t byte_index; + uint8_t bit_index; + int8_t endian; + uint8_t top; + uint8_t bot; + uint8_t ss; + uint8_t ssv; +}; + +struct fsk_data_state { + dsp_fsk_handle_t *fsk1200_handle; + uint8_t init; + uint8_t *buf; + size_t bufsize; + size_t blen; + size_t bpos; + size_t dlen; + size_t ppos; + int checksum; +}; + +typedef struct bitstream bitstream_t; +typedef struct fsk_data_state fsk_data_state_t; +typedef switch_status_t (*fsk_write_sample_t)(int16_t *buf, size_t buflen, void *user_data); + +struct fsk_modulator { + teletone_dds_state_t dds; + bitstream_t bs; + uint32_t carrier_bits_start; + uint32_t carrier_bits_stop; + uint32_t chan_sieze_bits; + uint32_t bit_factor; + uint32_t bit_accum; + uint32_t sample_counter; + int32_t samples_per_bit; + int32_t est_bytes; + fsk_modem_types_t modem_type; + fsk_data_state_t *fsk_data; + fsk_write_sample_t write_sample_callback; + void *user_data; + int16_t sample_buffer[64]; +}; + + +typedef int (*fsk_data_decoder_t)(fsk_data_state_t *state); + +typedef void (*logger_t)(const char *file, const char *func, int line, int level, const char *fmt, ...); +typedef struct fsk_modulator fsk_modulator_t; + +switch_status_t fsk_data_init(fsk_data_state_t *state, uint8_t *data, uint32_t datalen); +void bitstream_init(bitstream_t *bsp, uint8_t *data, uint32_t datalen, endian_t endian, uint8_t ss); +int8_t bitstream_get_bit(bitstream_t *bsp); +switch_status_t fsk_data_add_mdmf(fsk_data_state_t *state, mdmf_type_t type, const uint8_t *data, uint32_t datalen); +switch_status_t fsk_data_add_checksum(fsk_data_state_t *state); +switch_status_t fsk_data_parse(fsk_data_state_t *state, size_t *type, char **data, size_t *len); +switch_status_t fsk_demod_feed(fsk_data_state_t *state, int16_t *data, size_t samples); +switch_status_t fsk_demod_destroy(fsk_data_state_t *state); +int fsk_demod_init(fsk_data_state_t *state, int rate, uint8_t *buf, size_t bufsize); +size_t fsk_modulator_generate_bit(fsk_modulator_t *fsk_trans, int8_t bit, int16_t *buf, size_t buflen); +int32_t fsk_modulator_generate_carrier_bits(fsk_modulator_t *fsk_trans, uint32_t bits); +void fsk_modulator_generate_chan_sieze(fsk_modulator_t *fsk_trans); +void fsk_modulator_send_data(fsk_modulator_t *fsk_trans); +switch_status_t fsk_modulator_init(fsk_modulator_t *fsk_trans, + fsk_modem_types_t modem_type, + uint32_t sample_rate, + fsk_data_state_t *fsk_data, + float db_level, + uint32_t carrier_bits_start, + uint32_t carrier_bits_stop, + uint32_t chan_sieze_bits, + fsk_write_sample_t write_sample_callback, + void *user_data); + + +#define fsk_modulator_send_all(_it) fsk_modulator_generate_chan_sieze(_it); \ + fsk_modulator_generate_carrier_bits(_it, _it->carrier_bits_start); \ + fsk_modulator_send_data(_it); \ + fsk_modulator_generate_carrier_bits(_it, _it->carrier_bits_stop) + +SWITCH_END_EXTERN_C +#endif diff --git a/src/mod/applications/mod_fsk/mod_fsk.c b/src/mod/applications/mod_fsk/mod_fsk.c new file mode 100644 index 0000000000..9802353075 --- /dev/null +++ b/src/mod/applications/mod_fsk/mod_fsk.c @@ -0,0 +1,486 @@ +/* + * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * Copyright (C) 2005-2011, 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 + * + * mod_fsk.c -- FSK data transfer + * + */ +#include +#include "fsk_callerid.h" + +/* Prototypes */ +SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_fsk_shutdown); +SWITCH_MODULE_RUNTIME_FUNCTION(mod_fsk_runtime); +SWITCH_MODULE_LOAD_FUNCTION(mod_fsk_load); + +/* SWITCH_MODULE_DEFINITION(name, load, shutdown, runtime) + * Defines a switch_loadable_module_function_table_t and a static const char[] modname + */ +SWITCH_MODULE_DEFINITION(mod_fsk, mod_fsk_load, mod_fsk_shutdown, NULL); + +switch_status_t my_write_sample(int16_t *buf, size_t buflen, void *user_data) +{ + switch_buffer_t *buffer = (switch_buffer_t *) user_data; + + switch_buffer_write(buffer, buf, buflen * 2); + + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t write_fsk_data(uint32_t rate, int32_t db, switch_buffer_t *buffer, switch_event_t *event, const char *prefix) +{ + fsk_modulator_t fsk_trans; + fsk_data_state_t fsk_data = {0}; + uint8_t databuf[1024] = ""; + char time_str[9]; + struct tm tm; + time_t now; + switch_event_header_t *hp; + switch_size_t plen = 0; + + memset(&fsk_trans, 0, sizeof(fsk_trans)); + + time(&now); + localtime_r(&now, &tm); + strftime(time_str, sizeof(time_str), "%m%d%H%M", &tm); + + fsk_data_init(&fsk_data, databuf, sizeof(databuf)); + fsk_data_add_mdmf(&fsk_data, MDMF_DATETIME, (uint8_t *)time_str, strlen(time_str)); + + if (prefix) { + plen = strlen(prefix); + } + + + if (event) { + for (hp = event->headers; hp; hp = hp->next) { + char *packed; + char *name = hp->name; + + if (plen && strncasecmp(name, prefix, plen)) { + continue; + } + + name += plen; + + if (zstr(name)) { + continue; + } + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Encoding [%s][%s]\n", hp->name, hp->value); + + if (!strcasecmp(name, "phone_num")) { + fsk_data_add_mdmf(&fsk_data, MDMF_PHONE_NUM, (uint8_t *)hp->value, strlen(hp->value)); + } else if (!strcasecmp(name, "phone_name")) { + fsk_data_add_mdmf(&fsk_data, MDMF_PHONE_NAME, (uint8_t *)hp->value, strlen(hp->value)); + } else { + packed = switch_mprintf("%q:%q", name, hp->value); + fsk_data_add_mdmf(&fsk_data, MDMF_NAME_VALUE, (uint8_t *)packed, strlen(packed)); + free(packed); + } + } + } + + fsk_data_add_checksum(&fsk_data); + + fsk_modulator_init(&fsk_trans, FSK_BELL202, rate, &fsk_data, db, 180, 5, 300, my_write_sample, buffer); + fsk_modulator_send_all((&fsk_trans)); + + fsk_demod_destroy(&fsk_data); + + return SWITCH_STATUS_SUCCESS; +} + + +SWITCH_STANDARD_APP(fsk_send_function) { + switch_event_t *event = NULL; + switch_buffer_t *buffer; + switch_slin_data_t sdata = { 0 }; + switch_channel_t *channel = switch_core_session_get_channel(session); + switch_frame_t *read_frame; + switch_status_t status; + + + if (data) { + switch_ivr_sleep(session, 1000, SWITCH_TRUE, NULL); + switch_core_session_send_dtmf_string(session, (const char *) data); + switch_ivr_sleep(session, 1500, SWITCH_TRUE, NULL); + } + + if (switch_core_session_set_codec_slin(session, &sdata) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), + SWITCH_LOG_ERROR, "FAILURE\n"); + return; + } + + switch_buffer_create_dynamic(&buffer, 1024, 2048, 0); + + switch_channel_get_variables(channel, &event); + + write_fsk_data(sdata.codec.implementation->actual_samples_per_second, -14, buffer, event, "fsk_"); + + while(switch_channel_ready(channel)) { + status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0); + + if (!SWITCH_READ_ACCEPTABLE(status)) { + break; + } + + if ((sdata.write_frame.datalen = switch_buffer_read(buffer, sdata.write_frame.data, + sdata.codec.implementation->decoded_bytes_per_packet)) <= 0) { + break; + } + + + if (sdata.write_frame.datalen < sdata.codec.implementation->decoded_bytes_per_packet) { + memset((char *)sdata.write_frame.data + sdata.write_frame.datalen, 255, + sdata.codec.implementation->decoded_bytes_per_packet - sdata.write_frame.datalen); + sdata.write_frame.datalen = sdata.codec.implementation->decoded_bytes_per_packet; + } + sdata.write_frame.samples = sdata.write_frame.datalen / 2; + switch_core_session_write_frame(sdata.session, &sdata.write_frame, SWITCH_IO_FLAG_NONE, 0); + } + + switch_buffer_destroy(&buffer); + switch_core_codec_destroy(&sdata.codec); + switch_core_session_set_read_codec(session, NULL); + +} + +typedef struct { + switch_core_session_t *session; + fsk_data_state_t fsk_data; + uint8_t fbuf[512]; + int skip; +} switch_fsk_detect_t; + + + + +static switch_bool_t fsk_detect_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type) +{ + switch_fsk_detect_t *pvt = (switch_fsk_detect_t *) user_data; + //switch_frame_t *frame = NULL; + switch_channel_t *channel = switch_core_session_get_channel(pvt->session); + + switch (type) { + case SWITCH_ABC_TYPE_INIT: { + switch_codec_implementation_t read_impl = { 0 }; + switch_core_session_get_read_impl(pvt->session, &read_impl); + + if (fsk_demod_init(&pvt->fsk_data, read_impl.actual_samples_per_second, pvt->fbuf, sizeof(pvt->fbuf))) { + return SWITCH_FALSE; + } + + break; + } + case SWITCH_ABC_TYPE_CLOSE: + { + fsk_demod_destroy(&pvt->fsk_data); + } + break; + + case SWITCH_ABC_TYPE_WRITE_REPLACE: + case SWITCH_ABC_TYPE_READ_REPLACE: + { + switch_frame_t *rframe; + + if (type == SWITCH_ABC_TYPE_READ_REPLACE) { + rframe = switch_core_media_bug_get_read_replace_frame(bug); + } else { + rframe = switch_core_media_bug_get_write_replace_frame(bug); + } + + if (!pvt->skip && fsk_demod_feed(&pvt->fsk_data, rframe->data, rframe->datalen / 2) != SWITCH_STATUS_SUCCESS) { + char str[1024] = ""; + size_t type, mlen; + char *sp; + switch_event_t *event; + const char *app_var; + + switch_event_create_plain(&event, SWITCH_EVENT_CHANNEL_DATA); + + while(fsk_data_parse(&pvt->fsk_data, &type, &sp, &mlen) == SWITCH_STATUS_SUCCESS) { + char *varname = NULL, *val, *p; + + switch_copy_string(str, sp, mlen+1); + *(str+mlen) = '\0'; + switch_clean_string(str); + //printf("TYPE %u LEN %u VAL [%s]\n", (unsigned)type, (unsigned)mlen, str); + + val = str; + + switch(type) { + case MDMF_DATETIME: + varname = "fsk_datetime"; + break; + case MDMF_PHONE_NAME: + varname = "fsk_phone_name"; + break; + case MDMF_PHONE_NUM: + varname = "fsk_phone_num"; + break; + case MDMF_NAME_VALUE: + varname = switch_core_session_sprintf(pvt->session, "fsk_%s", val); + if ((p = strchr(varname, ':'))) { + *p++ = '\0'; + val = p; + } + break; + default: + break; + } + + if (varname && val) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_DEBUG, "%s setting FSK var [%s][%s]\n", + switch_channel_get_name(channel), varname, val); + switch_channel_set_variable(channel, varname, val); + if (event) { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, varname, val); + } + } + } + + if (event) { + if (switch_core_session_queue_event(pvt->session, &event) != SWITCH_STATUS_SUCCESS) { + switch_event_destroy(&event); + } + } + + if ((app_var = switch_channel_get_variable(channel, "execute_on_fsk"))) { + char *app_arg; + + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_DEBUG, "%s processing execute_on_fsk [%s]\n", + switch_channel_get_name(channel), app_var); + if ((app_arg = strchr(app_var, ' '))) { + *app_arg++ = '\0'; + } + switch_core_session_execute_application(pvt->session, app_var, app_arg); + } + + pvt->skip = 10; + } + + memset(rframe->data, 255, rframe->datalen); + + if (type == SWITCH_ABC_TYPE_READ_REPLACE) { + switch_core_media_bug_set_read_replace_frame(bug, rframe); + } else { + switch_core_media_bug_set_write_replace_frame(bug, rframe); + } + + if (pvt->skip && !--pvt->skip) { + return SWITCH_FALSE; + } + + } + break; + case SWITCH_ABC_TYPE_WRITE: + default: + break; + } + + return SWITCH_TRUE; +} + +switch_status_t stop_fsk_detect_session(switch_core_session_t *session) +{ + switch_media_bug_t *bug; + switch_channel_t *channel = switch_core_session_get_channel(session); + + if ((bug = switch_channel_get_private(channel, "fsk"))) { + switch_channel_set_private(channel, "fsk", NULL); + switch_core_media_bug_remove(session, &bug); + return SWITCH_STATUS_SUCCESS; + } + return SWITCH_STATUS_FALSE; +} + +switch_status_t fsk_detect_session(switch_core_session_t *session, const char *flags) +{ + switch_channel_t *channel = switch_core_session_get_channel(session); + switch_media_bug_t *bug; + switch_status_t status; + switch_fsk_detect_t *pvt = { 0 }; + switch_codec_implementation_t read_impl = { 0 }; + int bflags = SMBF_READ_REPLACE; + + if (strchr(flags, 'w')) { + bflags = SMBF_WRITE_REPLACE; + } + + switch_core_session_get_read_impl(session, &read_impl); + + if (!(pvt = switch_core_session_alloc(session, sizeof(*pvt)))) { + return SWITCH_STATUS_MEMERR; + } + + pvt->session = session; + + + if (switch_channel_pre_answer(channel) != SWITCH_STATUS_SUCCESS) { + return SWITCH_STATUS_FALSE; + } + + if ((status = switch_core_media_bug_add(session, "fsk_detect", NULL, + fsk_detect_callback, pvt, 0, bflags | SMBF_NO_PAUSE, &bug)) != SWITCH_STATUS_SUCCESS) { + return status; + } + + switch_channel_set_private(channel, "fsk", bug); + + return SWITCH_STATUS_SUCCESS; +} + + +SWITCH_STANDARD_APP(fsk_recv_function) +{ + fsk_detect_session(session, data); +} + +SWITCH_STANDARD_APP(fsk_display_function) +{ + /* expected to be called via 'execute_on_fsk' -- passes display update over FSK */ + + const char *cid_name, *cid_num; + switch_channel_t *channel = switch_core_session_get_channel(session); + switch_core_session_message_t *msg; + switch_core_session_t *psession, *usession = NULL; + char *flags = (char *) data; + + cid_name = switch_channel_get_variable(channel, "fsk_phone_name"); + cid_num = switch_channel_get_variable(channel, "fsk_phone_num"); + + if (zstr(cid_name)) { + cid_name = cid_num; + } + + if (zstr(cid_num)) { + return; + } + + if (strchr(flags, 'b')) { + if (switch_core_session_get_partner(session, &psession) == SWITCH_STATUS_SUCCESS) { + usession = psession; + } + } + + if (!usession) { + usession = session; + } + + msg = switch_core_session_alloc(usession, sizeof(*msg)); + MESSAGE_STAMP_FFL(msg); + msg->message_id = SWITCH_MESSAGE_INDICATE_DISPLAY; + msg->string_array_arg[0] = switch_core_session_strdup(usession, cid_name); + msg->string_array_arg[1] = switch_core_session_strdup(usession, cid_num); + msg->from = __FILE__; + switch_core_session_queue_message(usession, msg); + + if (psession) { + switch_core_session_rwunlock(psession); + psession = NULL; + } +} + +SWITCH_STANDARD_APP(fsk_simplify_function) +{ + /* expected to be called via 'execute_on_fsk' -- redirects call to point-to-point and eliminates legs in the middle */ + switch_channel_t *channel = switch_core_session_get_channel(session); + const char *sip_uri, *fsk_simplify_profile, *fsk_simplify_context; + char *bridgeto; + + if (!(sip_uri = switch_channel_get_variable(channel, "fsk_uri"))) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "%s Missing URI field!\n", switch_channel_get_name(channel)); + } + + if (!(fsk_simplify_profile = switch_channel_get_variable(channel, "fsk_simplify_profile"))) { + fsk_simplify_profile = "internal"; + } + + fsk_simplify_context = switch_channel_get_variable(channel, "fsk_simplify_context"); + + if (!zstr(sip_uri)) { + switch_core_session_t *psession; + switch_channel_t *pchannel; + + bridgeto = switch_core_session_sprintf(session, "bridge:sofia/%s/sip:%s", fsk_simplify_profile, sip_uri); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s transfering to [%s]\n", + switch_channel_get_name(channel), bridgeto); + + + if (switch_core_session_get_partner(session, &psession) == SWITCH_STATUS_SUCCESS) { + pchannel = switch_core_session_get_channel(psession); + switch_channel_set_flag(pchannel, CF_REDIRECT); + switch_channel_set_flag(pchannel, CF_TRANSFER); + } + + switch_ivr_session_transfer(session, bridgeto, "inline", fsk_simplify_context); + + if (psession) { + switch_ivr_session_transfer(psession, "sleep:5000", "inline", NULL); + switch_core_session_rwunlock(psession); + } + } +} + +/* Macro expands to: switch_status_t mod_fsk_load(switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool) */ +SWITCH_MODULE_LOAD_FUNCTION(mod_fsk_load) +{ + switch_application_interface_t *app_interface; + + /* connect my internal structure to the blank pointer passed to me */ + *module_interface = switch_loadable_module_create_module_interface(pool, modname); + + SWITCH_ADD_APP(app_interface, "fsk_send", "fsk_send", NULL, fsk_send_function, NULL, SAF_NONE); + SWITCH_ADD_APP(app_interface, "fsk_recv", "fsk_recv", NULL, fsk_recv_function, NULL, SAF_NONE); + SWITCH_ADD_APP(app_interface, "fsk_simplify", "fsk_simplify", NULL, fsk_simplify_function, NULL, SAF_NONE); + SWITCH_ADD_APP(app_interface, "fsk_display", "fsk_display", NULL, fsk_display_function, NULL, SAF_NONE); + + /* indicate that the module should continue to be loaded */ + return SWITCH_STATUS_SUCCESS; +} + +/* + Called when the system shuts down + Macro expands to: switch_status_t mod_fsk_shutdown() */ +SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_fsk_shutdown) +{ + /* Cleanup dynamically allocated config settings */ + + return SWITCH_STATUS_SUCCESS; +} + +/* 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/src/mod/applications/mod_fsk/uart.c b/src/mod/applications/mod_fsk/uart.c new file mode 100644 index 0000000000..5e0dd85350 --- /dev/null +++ b/src/mod/applications/mod_fsk/uart.c @@ -0,0 +1,124 @@ + +/* + * uart.c + * + * Copyright (c) 2005 Robert Krten. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This module contains a simple 8-bit UART, which performs a callback + * with the decoded byte value. + * + * 2005 06 11 R. Krten created +*/ + +#include +#include +#include +#include + +#include "uart.h" + +/* + * dsp_uart_attr_init + * + * Initializes the attributes structure; this must be done before the + * attributes structure is used. +*/ + +void dsp_uart_attr_init (dsp_uart_attr_t *attr) +{ + memset (attr, 0, sizeof (*attr)); +} + +/* + * dsp_uart_attr_get_bytehandler + * dsp_uart_attr_set_bytehandler + * + * These functions get and set their respective elements from the + * attributes structure. If an error code is returned, it is just + * zero == ok, -1 == fail. +*/ + +bytehandler_func_t dsp_uart_attr_get_bytehandler(dsp_uart_attr_t *attr, void **bytehandler_arg) +{ + *bytehandler_arg = attr->bytehandler_arg; + return attr->bytehandler; +} + +void dsp_uart_attr_set_bytehandler(dsp_uart_attr_t *attr, bytehandler_func_t bytehandler, void *bytehandler_arg) +{ + attr->bytehandler = bytehandler; + attr->bytehandler_arg = bytehandler_arg; +} + +dsp_uart_handle_t *dsp_uart_create(dsp_uart_attr_t *attr) +{ + dsp_uart_handle_t *handle; + + handle = malloc(sizeof (*handle)); + if (handle) { + memset(handle, 0, sizeof (*handle)); + + /* fill the attributes member */ + memcpy(&handle->attr, attr, sizeof (*attr)); + } + return handle; +} + +void dsp_uart_destroy(dsp_uart_handle_t **handle) +{ + if (*handle) { + free(*handle); + *handle = NULL; + } +} + + +void dsp_uart_bit_handler(void *x, int bit) +{ + dsp_uart_handle_t *handle = (dsp_uart_handle_t *) x; + + if (!handle->have_start) { + if (bit) { + return; /* waiting for start bit (0) */ + } + handle->have_start = 1; + handle->data = 0; + handle->nbits = 0; + return; + } + + handle->data >>= 1; + handle->data |= 0x80 * !!bit; + handle->nbits++; + + if (handle->nbits == 8) { + handle->attr.bytehandler(handle->attr.bytehandler_arg, handle->data); + handle->nbits = 0; + handle->data = 0; + handle->have_start = 0; + } +/* might consider handling errors in the future... */ +} + diff --git a/src/mod/applications/mod_fsk/uart.h b/src/mod/applications/mod_fsk/uart.h new file mode 100644 index 0000000000..89c3a13abc --- /dev/null +++ b/src/mod/applications/mod_fsk/uart.h @@ -0,0 +1,76 @@ +/* + * uart.h + * + * Copyright (c) 2005 Robert Krten. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This module contains the manifest constants and declarations for + * the UART module. + * + * 2005 06 19 R. Krten created +*/ + +#ifndef __UART_H__ +#define __UART_H__ + +typedef void (*bytehandler_func_t) (void *, int); +typedef void (*bithandler_func_t) (void *, int); + + +typedef struct dsp_uart_attr_s +{ + bytehandler_func_t bytehandler; /* byte handler */ + void *bytehandler_arg; /* arbitrary ID passed to bytehandler as first argument */ +} dsp_uart_attr_t; + +typedef struct +{ + dsp_uart_attr_t attr; + int have_start; /* wait for start bit to show up */ + int data; /* data buffer */ + int nbits; /* number of bits accumulated so far */ +} dsp_uart_handle_t; + +/* + * Function prototypes + * + * General calling order is: + * a) create the attributes structure (dsp_uart_attr_init) + * b) initialize fields in the attributes structure (dsp_uart_attr_set_*) + * c) create a Bell-202 handle (dsp_uart_create) + * d) feed bits through dsp_uart_bit_handler +*/ + +void dsp_uart_attr_init(dsp_uart_attr_t *attributes); + +bytehandler_func_t dsp_uart_attr_get_bytehandler(dsp_uart_attr_t *attributes, void **bytehandler_arg); +void dsp_uart_attr_set_bytehandler(dsp_uart_attr_t *attributes, bytehandler_func_t bytehandler, void *bytehandler_arg); + +dsp_uart_handle_t * dsp_uart_create(dsp_uart_attr_t *attributes); +void dsp_uart_destroy(dsp_uart_handle_t **handle); + +void dsp_uart_bit_handler(void *handle, int bit); + +#endif + From 4fd043e3fb69a55dee43353547f2fb1fa24e7788 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 10 Jan 2011 17:27:01 -0600 Subject: [PATCH 22/29] add mod_fsk --- build/modules.conf.in | 1 + 1 file changed, 1 insertion(+) diff --git a/build/modules.conf.in b/build/modules.conf.in index 69d90a8dd4..2be000f6b3 100644 --- a/build/modules.conf.in +++ b/build/modules.conf.in @@ -35,6 +35,7 @@ applications/mod_valet_parking #applications/mod_snapshot #applications/mod_snipe_hunt #applications/mod_callcenter +#applications/mod_fsk codecs/mod_g723_1 codecs/mod_amr #codecs/mod_amrwb From b55db357d93c72ca712feb1e3ee91b60f026bdbf Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 10 Jan 2011 17:27:05 -0600 Subject: [PATCH 23/29] add mod_fsk --- conf/autoload_configs/modules.conf.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/conf/autoload_configs/modules.conf.xml b/conf/autoload_configs/modules.conf.xml index 51c62f2059..b7100bd304 100644 --- a/conf/autoload_configs/modules.conf.xml +++ b/conf/autoload_configs/modules.conf.xml @@ -56,6 +56,7 @@ + From 6f103acd796ebcd7c0001a8d58568a3d77d2b3e6 Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Tue, 11 Jan 2011 09:40:59 -0600 Subject: [PATCH 24/29] merge code from xml-rpc trunk - fix xml-rpc not terminating on windows on fs unload - only effect windows build --- libs/xmlrpc-c/lib/abyss/src/socket_win.c | 143 +++++++++++++++-------- 1 file changed, 97 insertions(+), 46 deletions(-) diff --git a/libs/xmlrpc-c/lib/abyss/src/socket_win.c b/libs/xmlrpc-c/lib/abyss/src/socket_win.c index 92b2b99cfb..d3f683a439 100644 --- a/libs/xmlrpc-c/lib/abyss/src/socket_win.c +++ b/libs/xmlrpc-c/lib/abyss/src/socket_win.c @@ -9,8 +9,7 @@ #include #include #include -#include -#include +#include #include "xmlrpc_config.h" #include "xmlrpc-c/util_int.h" @@ -249,6 +248,7 @@ struct socketWin { SOCKET winsock; bool userSuppliedWinsock; /* 'socket' was supplied by the user; it belongs to him */ + HANDLE interruptEvent; }; static @@ -322,6 +322,8 @@ channelDestroy(TChannel * const channelP) { if (!socketWinP->userSuppliedWinsock) closesocket(socketWinP->winsock); + CloseHandle(socketWinP->interruptEvent); + free(socketWinP); } @@ -430,9 +432,9 @@ channelWait(TChannel * const channelP, timedOut = TRUE; break; case -1: /* socket error */ - if (errno != EINTR) + if (WSAGetLastError() != WSAEINTR) failed = TRUE; - break; + break; default: if (FD_ISSET(socketWinP->winsock, &rfds)) readRdy = TRUE; @@ -460,7 +462,9 @@ channelInterrupt(TChannel * const channelP) { now or in the future. Actually, this is just a no-op because we don't yet know how to - accomplish that. + accomplish that. (But we could probably do it the same way + chanSwitchInterrupt() works -- no one has needed it enough yet to do that + work). -----------------------------------------------------------------------------*/ } @@ -484,7 +488,7 @@ ChannelWinGetPeerName(TChannel * const channelP, if (rc != 0) { int const lastError = WSAGetLastError(); - xmlrpc_asprintf(errorP, "getpeername() failed. WSAERROR = %d (%s)", + xmlrpc_asprintf(errorP, "getpeername() failed. WSA error = %d (%s)", lastError, getWSAError(lastError)); } else { if (addrlen != sizeof(sockAddr)) @@ -581,7 +585,8 @@ makeChannelFromWinsock(SOCKET const winsock, socketWinP->winsock = winsock; socketWinP->userSuppliedWinsock = TRUE; - + socketWinP->interruptEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + ChannelCreate(&channelVtbl, socketWinP, &channelP); if (channelP == NULL) @@ -591,8 +596,10 @@ makeChannelFromWinsock(SOCKET const winsock, *channelPP = channelP; *errorP = NULL; } - if (*errorP) + if (*errorP) { + CloseHandle(socketWinP->interruptEvent); free(socketWinP); + } } } @@ -632,7 +639,7 @@ ChannelWinCreateWinsock(SOCKET const fd, socklen_t peerAddrLen; int rc; - peerAddrLen = sizeof(peerAddrLen); + peerAddrLen = sizeof(peerAddr); rc = getpeername(fd, &peerAddr, &peerAddrLen); @@ -676,6 +683,8 @@ chanSwitchDestroy(TChanSwitch * const chanSwitchP) { if (!socketWinP->userSuppliedWinsock) closesocket(socketWinP->winsock); + CloseHandle(socketWinP->interruptEvent); + free(socketWinP); } @@ -711,6 +720,49 @@ chanSwitchListen(TChanSwitch * const chanSwitchP, +static void +createChannelForAccept(int const acceptedWinsock, + struct sockaddr const peerAddr, + TChannel ** const channelPP, + void ** const channelInfoPP, + const char ** const errorP) { + + struct abyss_win_chaninfo * channelInfoP; + makeChannelInfo(&channelInfoP, peerAddr, sizeof(peerAddr), errorP); + if (!*errorP) { + struct socketWin * acceptedSocketP; + + MALLOCVAR(acceptedSocketP); + + if (!acceptedSocketP) + xmlrpc_asprintf(errorP, "Unable to allocate memory"); + else { + TChannel * channelP; + + acceptedSocketP->winsock = acceptedWinsock; + acceptedSocketP->userSuppliedWinsock = FALSE; + acceptedSocketP->interruptEvent = + CreateEvent(NULL, FALSE, FALSE, NULL); + + ChannelCreate(&channelVtbl, acceptedSocketP, &channelP); + if (!channelP) + xmlrpc_asprintf(errorP, + "Failed to create TChannel object."); + else { + *errorP = NULL; + *channelPP = channelP; + *channelInfoPP = channelInfoP; + } + if (*errorP) { + CloseHandle(acceptedSocketP->interruptEvent); + free(acceptedSocketP); + } + } + } +} + + + static SwitchAcceptImpl chanSwitchAccept; static void @@ -728,7 +780,7 @@ chanSwitchAccept(TChanSwitch * const chanSwitchP, *channelPP == NULL. -----------------------------------------------------------------------------*/ struct socketWin * const listenSocketP = chanSwitchP->implP; - + HANDLE acceptEvent = WSACreateEvent(); bool interrupted; TChannel * channelP; @@ -736,46 +788,44 @@ chanSwitchAccept(TChanSwitch * const chanSwitchP, channelP = NULL; /* No connection yet */ *errorP = NULL; /* No error yet */ + WSAEventSelect(listenSocketP->winsock, acceptEvent, + FD_ACCEPT | FD_CLOSE | FD_READ); + while (!channelP && !*errorP && !interrupted) { + HANDLE interrupts[2] = {acceptEvent, listenSocketP->interruptEvent}; + int rc; struct sockaddr peerAddr; socklen_t size = sizeof(peerAddr); - int rc; + + rc = WaitForMultipleObjects(2, interrupts, FALSE, INFINITE); + if (WAIT_OBJECT_0 + 1 == rc) { + interrupted = TRUE; + continue; + }; rc = accept(listenSocketP->winsock, &peerAddr, &size); if (rc >= 0) { int const acceptedWinsock = rc; - struct socketWin * acceptedSocketP; - MALLOCVAR(acceptedSocketP); + createChannelForAccept(acceptedWinsock, peerAddr, + &channelP, channelInfoPP, errorP); - if (!acceptedSocketP) - xmlrpc_asprintf(errorP, "Unable to allocate memory"); - else { - acceptedSocketP->winsock = acceptedWinsock; - acceptedSocketP->userSuppliedWinsock = FALSE; - - *channelInfoPP = NULL; - - ChannelCreate(&channelVtbl, acceptedSocketP, &channelP); - if (!channelP) - xmlrpc_asprintf(errorP, - "Failed to create TChannel object."); - else - *errorP = NULL; - - if (*errorP) - free(acceptedSocketP); - } if (*errorP) closesocket(acceptedWinsock); - } else if (errno == EINTR) - interrupted = TRUE; - else - xmlrpc_asprintf(errorP, "accept() failed, errno = %d (%s)", - errno, strerror(errno)); + } else { + int const lastError = WSAGetLastError(); + + if (lastError == WSAEINTR) + interrupted = TRUE; + else + xmlrpc_asprintf(errorP, + "accept() failed, WSA error = %d (%s)", + lastError, getWSAError(lastError)); + } } *channelPP = channelP; + CloseHandle(acceptEvent); } @@ -787,15 +837,10 @@ chanSwitchInterrupt(TChanSwitch * const chanSwitchP) { /*---------------------------------------------------------------------------- Interrupt any waiting that a thread might be doing in chanSwitchAccept() now or in the future. - - Actually, this is just a no-op because we don't yet know how to - accomplish that. -----------------------------------------------------------------------------*/ - struct socketWin * const socketWinP = chanSwitchP->implP; - - if (!socketWinP->userSuppliedWinsock) - closesocket(socketWinP->winsock); + struct socketWin * const listenSocketP = chanSwitchP->implP; + SetEvent(listenSocketP->interruptEvent); } @@ -889,6 +934,7 @@ ChanSwitchWinCreate(uint16_t const portNumber, } else { socketWinP->winsock = winsock; socketWinP->userSuppliedWinsock = FALSE; + socketWinP->interruptEvent = CreateEvent(NULL, FALSE, FALSE, NULL); setSocketOptions(socketWinP->winsock, errorP); if (!*errorP) { @@ -899,8 +945,10 @@ ChanSwitchWinCreate(uint16_t const portNumber, chanSwitchPP); } - if (*errorP) + if (*errorP) { + CloseHandle(socketWinP->interruptEvent); closesocket(winsock); + } } if (*errorP) free(socketWinP); @@ -929,7 +977,8 @@ ChanSwitchWinCreateWinsock(SOCKET const winsock, socketWinP->winsock = winsock; socketWinP->userSuppliedWinsock = TRUE; - + socketWinP->interruptEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + ChanSwitchCreate(&chanSwitchVtbl, socketWinP, &chanSwitchP); if (chanSwitchP == NULL) @@ -939,8 +988,10 @@ ChanSwitchWinCreateWinsock(SOCKET const winsock, *chanSwitchPP = chanSwitchP; *errorP = NULL; } - if (*errorP) + if (*errorP) { + CloseHandle(socketWinP->interruptEvent); free(socketWinP); + } } } } From 54421f591015496fd3c0c3da7a5221a84ab7c8e3 Mon Sep 17 00:00:00 2001 From: Michael Jerris Date: Tue, 11 Jan 2011 13:11:59 -0500 Subject: [PATCH 25/29] mod_voicemail: add events for record/change greeting and record name --- .../mod_voicemail/mod_voicemail.c | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/mod/applications/mod_voicemail/mod_voicemail.c b/src/mod/applications/mod_voicemail/mod_voicemail.c index 851ec77c61..1799e5c7dc 100644 --- a/src/mod/applications/mod_voicemail/mod_voicemail.c +++ b/src/mod/applications/mod_voicemail/mod_voicemail.c @@ -1973,12 +1973,22 @@ static void voicemail_check_main(switch_core_session_t *session, vm_profile_t *p if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_BREAK) { TRY_CODE(switch_ivr_phrase_macro(session, VM_CHOOSE_GREETING_FAIL_MACRO, NULL, NULL, NULL)); } else { + switch_event_t *params; + TRY_CODE(switch_ivr_phrase_macro(session, VM_CHOOSE_GREETING_SELECTED_MACRO, input, NULL, NULL)); sql = switch_mprintf("update voicemail_prefs set greeting_path='%s' where username='%s' and domain='%s'", file_path, myid, domain_name); vm_execute_sql(profile, sql, profile->mutex); switch_safe_free(sql); + + switch_event_create_subclass(¶ms, SWITCH_EVENT_CUSTOM, VM_EVENT_MAINT); + switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "VM-Action", "change-greeting"); + switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "VM-Greeting-Path", file_path); + switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "VM-User", myid); + switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "VM-Domain", domain_name); + switch_channel_event_set_data(channel, params); + switch_event_fire(¶ms); } switch_safe_free(file_path); } else if (!strcmp(input, profile->record_greeting_key)) { @@ -1989,6 +1999,7 @@ static void voicemail_check_main(switch_core_session_t *session, vm_profile_t *p if (num < 1 || num > VM_MAX_GREETINGS) { TRY_CODE(switch_ivr_phrase_macro(session, VM_CHOOSE_GREETING_FAIL_MACRO, NULL, NULL, NULL)); } else { + switch_event_t *params; file_path = switch_mprintf("%s%sgreeting_%d.%s", dir_path, SWITCH_PATH_SEPARATOR, num, profile->file_ext); TRY_CODE(create_file(session, profile, VM_RECORD_GREETING_MACRO, file_path, &message_len, SWITCH_TRUE, NULL, NULL)); sql = @@ -1997,6 +2008,14 @@ static void voicemail_check_main(switch_core_session_t *session, vm_profile_t *p vm_execute_sql(profile, sql, profile->mutex); switch_safe_free(sql); switch_safe_free(file_path); + + switch_event_create_subclass(¶ms, SWITCH_EVENT_CUSTOM, VM_EVENT_MAINT); + switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "VM-Action", "record-greeting"); + switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "VM-Greeting-Path", file_path); + switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "VM-User", myid); + switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "VM-Domain", domain_name); + switch_channel_event_set_data(channel, params); + switch_event_fire(¶ms); } } else if (!strcmp(input, profile->change_pass_key)) { @@ -2027,12 +2046,21 @@ static void voicemail_check_main(switch_core_session_t *session, vm_profile_t *p switch_event_fire(¶ms); } else if (!strcmp(input, profile->record_name_key)) { + switch_event_t *params; file_path = switch_mprintf("%s%srecorded_name.%s", dir_path, SWITCH_PATH_SEPARATOR, profile->file_ext); TRY_CODE(create_file(session, profile, VM_RECORD_NAME_MACRO, file_path, &message_len, SWITCH_FALSE, NULL, NULL)); sql = switch_mprintf("update voicemail_prefs set name_path='%s' where username='%s' and domain='%s'", file_path, myid, domain_name); vm_execute_sql(profile, sql, profile->mutex); switch_safe_free(file_path); switch_safe_free(sql); + + switch_event_create_subclass(¶ms, SWITCH_EVENT_CUSTOM, VM_EVENT_MAINT); + switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "VM-Action", "record-name"); + switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "VM-Name-Path", file_path); + switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "VM-User", myid); + switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "VM-Domain", domain_name); + switch_channel_event_set_data(channel, params); + switch_event_fire(¶ms); } continue; } From a9eb0aa6efd0aff8ab64e597429757fdf1939c46 Mon Sep 17 00:00:00 2001 From: Michael Jerris Date: Tue, 11 Jan 2011 13:12:15 -0500 Subject: [PATCH 26/29] attempt to quick fix solaris build --- Makefile.am | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index df1ee2e0d0..8d35068c35 100644 --- a/Makefile.am +++ b/Makefile.am @@ -251,7 +251,8 @@ libfreeswitch_la_SOURCES = \ libs/miniupnpc/upnperrors.c \ libs/libnatpmp/natpmp.c \ libs/libnatpmp/getgateway.c\ - libs/spandsp/src/plc.c + libs/spandsp/src/plc.c \ + libs/spandsp/src/bit_operations.c if ENABLE_CPP libfreeswitch_la_SOURCES += src/switch_cpp.cpp From d41e6498f19e100eb8e9241784bb271b1e66c831 Mon Sep 17 00:00:00 2001 From: Brian West Date: Tue, 11 Jan 2011 12:25:41 -0600 Subject: [PATCH 27/29] Set route header as a var on channel like Diversion header --- src/mod/endpoints/mod_sofia/sofia.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 381eb5d2d1..9145d2a2e7 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -7098,7 +7098,15 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_ /* Loop thru unknown Headers Here so we can do something with them */ for (un = sip->sip_unknown; un; un = un->un_next) { - if (!strncasecmp(un->un_name, "Diversion", 9)) { + if (!strncasecmp(un->un_name, "Route", 5)) { + if (!zstr(un->un_value)) { + char *tmp_name; + if ((tmp_name = switch_mprintf("%s%s", SOFIA_SIP_HEADER_PREFIX, un->un_name))) { + switch_channel_set_variable(channel, tmp_name, un->un_value); + free(tmp_name); + } + } + } else if (!strncasecmp(un->un_name, "Diversion", 9)) { /* Basic Diversion Support for Diversion Indication in SIP */ /* draft-levy-sip-diversion-08 */ if (!zstr(un->un_value)) { From ef880c53b2dc730e212af914e1ac4fc9753eb5d2 Mon Sep 17 00:00:00 2001 From: Brian West Date: Tue, 11 Jan 2011 13:41:50 -0600 Subject: [PATCH 28/29] Route is not an un-named header its named. Handled like full_via and full_from and such --- src/mod/endpoints/mod_sofia/sofia.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 9145d2a2e7..904f3ecb46 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -161,6 +161,15 @@ static void extract_header_vars(sofia_profile_t *profile, sip_t const *sip, swit char *full; if (sip) { + if (sip->sip_route) { + if ((full = sip_header_as_string(profile->home, (void *) sip->sip_route))) { + const char *v = switch_channel_get_variable(channel, "sip_full_route"); + if (!v) { + switch_channel_set_variable(channel, "sip_full_route", full); + } + su_free(profile->home, full); + } + } if (sip->sip_via) { if ((full = sip_header_as_string(profile->home, (void *) sip->sip_via))) { const char *v = switch_channel_get_variable(channel, "sip_full_via"); @@ -7098,15 +7107,7 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_ /* Loop thru unknown Headers Here so we can do something with them */ for (un = sip->sip_unknown; un; un = un->un_next) { - if (!strncasecmp(un->un_name, "Route", 5)) { - if (!zstr(un->un_value)) { - char *tmp_name; - if ((tmp_name = switch_mprintf("%s%s", SOFIA_SIP_HEADER_PREFIX, un->un_name))) { - switch_channel_set_variable(channel, tmp_name, un->un_value); - free(tmp_name); - } - } - } else if (!strncasecmp(un->un_name, "Diversion", 9)) { + if (!strncasecmp(un->un_name, "Diversion", 9)) { /* Basic Diversion Support for Diversion Indication in SIP */ /* draft-levy-sip-diversion-08 */ if (!zstr(un->un_value)) { From 45340d8017c1915e4353961022e8c08d1f1eb7a8 Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Tue, 11 Jan 2011 16:20:05 -0500 Subject: [PATCH 29/29] freetdm: added fix for hangup cause sometimes set to 0 during glare --- .../ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 2b43e9cea5..7b7c748c7a 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 @@ -605,7 +605,7 @@ void sngisdn_process_rel_ind (sngisdn_event_data_t *sngisdn_event) ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "cause:%d\n", ftdmchan->caller_data.hangup_cause); } else { ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "RELEASE COMPLETE did not have a cause code\n"); - ftdmchan->caller_data.hangup_cause = 0; + ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_REQUESTED_CHAN_UNAVAIL; } sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_ABORT);