diff --git a/Freeswitch.2008.express.sln b/Freeswitch.2008.express.sln index b4f1f60201..43cbc02d0e 100644 --- a/Freeswitch.2008.express.sln +++ b/Freeswitch.2008.express.sln @@ -9,12 +9,14 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FreeSwitchConsole", "w32\Co EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FreeSwitchCoreLib", "w32\Library\FreeSwitchCore.2008.vcproj", "{202D7A4E-760D-4D0E-AFA1-D7459CED30FF}" ProjectSection(ProjectDependencies) = postProject + {D331904D-A00A-4694-A5A3-FCFF64AB5DBE} = {D331904D-A00A-4694-A5A3-FCFF64AB5DBE} {8D04B550-D240-4A44-8A18-35DA3F7038D9} = {8D04B550-D240-4A44-8A18-35DA3F7038D9} {89385C74-5860-4174-9CAF-A39E7C48909C} = {89385C74-5860-4174-9CAF-A39E7C48909C} {1CBB0077-18C5-455F-801C-0A0CE7B0BBF5} = {1CBB0077-18C5-455F-801C-0A0CE7B0BBF5} {F057DA7F-79E5-4B00-845C-EF446EF055E3} = {F057DA7F-79E5-4B00-845C-EF446EF055E3} {03207781-0D1C-4DB3-A71D-45C608F28DBD} = {03207781-0D1C-4DB3-A71D-45C608F28DBD} {F6C55D93-B927-4483-BB69-15AEF3DD2DFF} = {F6C55D93-B927-4483-BB69-15AEF3DD2DFF} + {87EE9DA4-DE1E-4448-8324-183C98DCA588} = {87EE9DA4-DE1E-4448-8324-183C98DCA588} {EEF031CB-FED8-451E-A471-91EC8D4F6750} = {EEF031CB-FED8-451E-A471-91EC8D4F6750} {6EDFEFD5-3596-4FA9-8EBA-B331547B35A3} = {6EDFEFD5-3596-4FA9-8EBA-B331547B35A3} EndProjectSection diff --git a/Freeswitch.2008.sln b/Freeswitch.2008.sln index f915005e7c..4061116d07 100644 --- a/Freeswitch.2008.sln +++ b/Freeswitch.2008.sln @@ -379,12 +379,14 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FreeSwitchConsole", "w32\Co EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FreeSwitchCoreLib", "w32\Library\FreeSwitchCore.2008.vcproj", "{202D7A4E-760D-4D0E-AFA1-D7459CED30FF}" ProjectSection(ProjectDependencies) = postProject + {D331904D-A00A-4694-A5A3-FCFF64AB5DBE} = {D331904D-A00A-4694-A5A3-FCFF64AB5DBE} {8D04B550-D240-4A44-8A18-35DA3F7038D9} = {8D04B550-D240-4A44-8A18-35DA3F7038D9} {89385C74-5860-4174-9CAF-A39E7C48909C} = {89385C74-5860-4174-9CAF-A39E7C48909C} {1CBB0077-18C5-455F-801C-0A0CE7B0BBF5} = {1CBB0077-18C5-455F-801C-0A0CE7B0BBF5} {F057DA7F-79E5-4B00-845C-EF446EF055E3} = {F057DA7F-79E5-4B00-845C-EF446EF055E3} {03207781-0D1C-4DB3-A71D-45C608F28DBD} = {03207781-0D1C-4DB3-A71D-45C608F28DBD} {F6C55D93-B927-4483-BB69-15AEF3DD2DFF} = {F6C55D93-B927-4483-BB69-15AEF3DD2DFF} + {87EE9DA4-DE1E-4448-8324-183C98DCA588} = {87EE9DA4-DE1E-4448-8324-183C98DCA588} {EEF031CB-FED8-451E-A471-91EC8D4F6750} = {EEF031CB-FED8-451E-A471-91EC8D4F6750} {6EDFEFD5-3596-4FA9-8EBA-B331547B35A3} = {6EDFEFD5-3596-4FA9-8EBA-B331547B35A3} EndProjectSection diff --git a/build/modules.conf.in b/build/modules.conf.in index d31bb31b76..1084461f0e 100644 --- a/build/modules.conf.in +++ b/build/modules.conf.in @@ -37,6 +37,7 @@ applications/mod_valet_parking #applications/mod_callcenter #applications/mod_fsk #applications/mod_ladspa +#applications/mod_mongo codecs/mod_g723_1 codecs/mod_amr #codecs/mod_amrwb diff --git a/build/sounds_version.txt b/build/sounds_version.txt index cb456d76eb..55729b1f9f 100644 --- a/build/sounds_version.txt +++ b/build/sounds_version.txt @@ -1,3 +1,3 @@ -en-us-callie 1.0.15 +en-us-callie 1.0.16 ru-RU-elena 1.0.12 diff --git a/conf/autoload_configs/mongo.conf.xml b/conf/autoload_configs/mongo.conf.xml new file mode 100644 index 0000000000..a7fdecae8d --- /dev/null +++ b/conf/autoload_configs/mongo.conf.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/configure.in b/configure.in index 389e4985b6..c396ffa3d6 100644 --- a/configure.in +++ b/configure.in @@ -808,6 +808,7 @@ SAC_OPENSSL if test x$HAVE_OPENSSL = x1; then openssl_CFLAGS="$openssl_CFLAGS -DHAVE_OPENSSL"; + APR_ADDTO(SWITCH_AM_CFLAGS, -DHAVE_OPENSSL) fi AX_CHECK_JAVA diff --git a/debian/freeswitch.conffiles b/debian/freeswitch.conffiles index 20da33de15..c765625b6f 100644 --- a/debian/freeswitch.conffiles +++ b/debian/freeswitch.conffiles @@ -22,6 +22,7 @@ /opt/freeswitch/conf/autoload_configs/logfile.conf.xml /opt/freeswitch/conf/autoload_configs/memcache.conf.xml /opt/freeswitch/conf/autoload_configs/modules.conf.xml +/opt/freeswitch/conf/autoload_configs/mongo.conf.xml /opt/freeswitch/conf/autoload_configs/nibblebill.conf.xml /opt/freeswitch/conf/autoload_configs/opal.conf.xml /opt/freeswitch/conf/autoload_configs/pocketsphinx.conf.xml diff --git a/debian/freeswitch.install b/debian/freeswitch.install index 37c1407d9c..72ded2c48c 100644 --- a/debian/freeswitch.install +++ b/debian/freeswitch.install @@ -29,6 +29,7 @@ opt/freeswitch/conf/autoload_configs/local_stream.conf.xml opt/freeswitch/conf/autoload_configs/logfile.conf.xml opt/freeswitch/conf/autoload_configs/memcache.conf.xml opt/freeswitch/conf/autoload_configs/modules.conf.xml +opt/freeswitch/conf/autoload_configs/mongo.conf.xml opt/freeswitch/conf/autoload_configs/nibblebill.conf.xml opt/freeswitch/conf/autoload_configs/opal.conf.xml opt/freeswitch/conf/autoload_configs/pocketsphinx.conf.xml diff --git a/docs/phrase/phrase_en.xml b/docs/phrase/phrase_en.xml index 9e31cccf08..507fc7bd34 100644 --- a/docs/phrase/phrase_en.xml +++ b/docs/phrase/phrase_en.xml @@ -5,6 +5,23 @@ + + + + + + + + + + + + + + + + + @@ -222,6 +239,8 @@ + + @@ -270,7 +289,13 @@ - + + + + + + + @@ -432,8 +457,6 @@ - - @@ -445,37 +468,14 @@ - - - - - - - - - - - - - - - - - - - - - - - @@ -489,6 +489,8 @@ + + diff --git a/freeswitch.spec b/freeswitch.spec index a266c1e919..d13ae2686d 100644 --- a/freeswitch.spec +++ b/freeswitch.spec @@ -63,12 +63,12 @@ Vendor: http://www.freeswitch.org/ # Source files and where to get them # ###################################################################################################################### -Source0: http://files.freeswitch.org/%{name}-%{version}.tar.bz2 +Source0: http://files.freeswitch.org/%{name}-%{version}.tar.bz2 Source1: http://files.freeswitch.org/downloads/libs/celt-0.10.0.tar.gz Source2: http://files.freeswitch.org/downloads/libs/flite-1.3.99-latest.tar.gz Source3: http://files.freeswitch.org/downloads/libs/lame-3.97.tar.gz Source4: http://files.freeswitch.org/downloads/libs/libshout-2.2.2.tar.gz -Source5: http://files.freeswitch.org/downloads/libs/mpg123.tar.gz +Source5: http://files.freeswitch.org/downloads/libs/mpg123-1.13.2.tar.gz Source6: http://files.freeswitch.org/downloads/libs/openldap-2.4.11.tar.gz Source7: http://files.freeswitch.org/downloads/libs/pocketsphinx-0.5.99-20091212.tar.gz Source8: http://files.freeswitch.org/downloads/libs/soundtouch-1.3.1.tar.gz @@ -776,6 +776,7 @@ fi %config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/logfile.conf.xml %config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/memcache.conf.xml %config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/modules.conf.xml +%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/mongo.conf.xml %config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/nibblebill.conf.xml %config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/opal.conf.xml %config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/osp.conf.xml diff --git a/libs/freetdm/configure.ac b/libs/freetdm/configure.ac index 55185cb10d..493f0da3b0 100644 --- a/libs/freetdm/configure.ac +++ b/libs/freetdm/configure.ac @@ -294,6 +294,19 @@ if test "${HAVE_SNG_SS7}" = "yes"; then fi fi + +## +# zlib (required for Sangoma SS7 Transparent IAM) +# +HAVE_ZLIB="no" +AC_MSG_RESULT([${as_nl}<<>> zlib]) +AC_CHECK_LIB([z], [compress], [HAVE_ZLIB="yes"]) +AC_MSG_RESULT([checking whether zlib is installed... ${HAVE_ZLIB}]) +AM_CONDITIONAL([HAVE_ZLIB], [test "{HAVE_ZLIB]" = "yes"]) +if test "${HAVE_ZLIB}" = "yes"; then + CFLAGS="$CFLAGS -DHAVE_ZLIB" +fi + ## # libisdn # diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index 4cc364c9f3..618f2501ff 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -130,6 +130,10 @@ struct span_config { int limit_calls; int limit_seconds; limit_reset_event_t limit_reset_event; + /* digital codec and digital sampling rate are used to configure the codec + * when bearer capability is set to unrestricted digital */ + const char *digital_codec; + int digital_sampling_rate; chan_pvt_t pvts[FTDM_MAX_CHANNELS_SPAN]; }; @@ -294,13 +298,11 @@ static void cycle_foreground(ftdm_channel_t *ftdmchan, int flash, const char *bc } } - - - -static switch_status_t tech_init(private_t *tech_pvt, switch_core_session_t *session, ftdm_channel_t *ftdmchan) +static switch_status_t tech_init(private_t *tech_pvt, switch_core_session_t *session, ftdm_channel_t *ftdmchan, ftdm_caller_data_t *caller_data) { const char *dname = NULL; uint32_t interval = 0, srate = 8000; + uint32_t span_id; ftdm_codec_t codec; tech_pvt->ftdmchan = ftdmchan; @@ -321,6 +323,16 @@ static switch_status_t tech_init(private_t *tech_pvt, switch_core_session_t *ses return SWITCH_STATUS_GENERR; } + span_id = ftdm_channel_get_span_id(ftdmchan); + if (caller_data->bearer_capability == FTDM_BEARER_CAP_UNRESTRICTED + && SPAN_CONFIG[span_id].digital_codec) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Initializing digital call with codec %s at %dhz.\n", + SPAN_CONFIG[span_id].digital_codec, SPAN_CONFIG[span_id].digital_sampling_rate); + dname = SPAN_CONFIG[span_id].digital_codec; + srate = SPAN_CONFIG[span_id].digital_sampling_rate; + goto init_codecs; + } + if (FTDM_SUCCESS != ftdm_channel_command(ftdmchan, FTDM_COMMAND_GET_CODEC, &codec)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to retrieve channel codec.\n"); return SWITCH_STATUS_GENERR; @@ -349,6 +361,7 @@ static switch_status_t tech_init(private_t *tech_pvt, switch_core_session_t *ses } } +init_codecs: if (switch_core_codec_init(&tech_pvt->read_codec, dname, @@ -1093,7 +1106,7 @@ static ftdm_status_t on_channel_found(ftdm_channel_t *fchan, ftdm_caller_data_t span_id = ftdm_channel_get_span_id(fchan); chan_id = ftdm_channel_get_id(fchan); - tech_init(hdata->tech_pvt, hdata->new_session, fchan); + tech_init(hdata->tech_pvt, hdata->new_session, fchan, caller_data); snprintf(name, sizeof(name), "FreeTDM/%u:%u/%s", span_id, chan_id, caller_data->dnis.digits); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Connect outbound channel %s\n", name); @@ -1366,7 +1379,15 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi ftdm_usrmsg_add_var(&usrmsg, "ss7_pres_ind", sipvar); } - + sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-CPC"); + if (sipvar) { + ftdm_set_calling_party_category(sipvar, (uint8_t *)&caller_data.cpc); + } + + sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-IAM"); + if (sipvar) { + ftdm_usrmsg_add_var(&usrmsg, "ss7_iam", sipvar); + } } if (switch_test_flag(outbound_profile, SWITCH_CPF_SCREEN)) { @@ -1439,7 +1460,13 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi if (!strncasecmp(h->name, FREETDM_VAR_PREFIX, FREETDM_VAR_PREFIX_LEN)) { char *v = h->name + FREETDM_VAR_PREFIX_LEN; if (!zstr(v)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Adding outbound freetdm variable %s=%s to channel %d:%d\n", v, h->value, span_id, chan_id); + if (!strcasecmp(v, "ss7_iam")) { + /* Do not print the value of ss7_iam as it is very long */ + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Adding outbound freetdm variable %s to channel %d:%d\n", v, span_id, chan_id); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Adding outbound freetdm variable %s=%s to channel %d:%d\n", v, h->value, span_id, chan_id); + } + ftdm_usrmsg_add_var(&usrmsg, v, h->value); } } @@ -1542,7 +1569,7 @@ ftdm_status_t ftdm_channel_from_event(ftdm_sigmsg_t *sigmsg, switch_core_session tech_pvt = (private_t *) switch_core_session_alloc(session, sizeof(private_t)); assert(tech_pvt != NULL); channel = switch_core_session_get_channel(session); - if (tech_init(tech_pvt, session, sigmsg->channel) != SWITCH_STATUS_SUCCESS) { + if (tech_init(tech_pvt, session, sigmsg->channel, channel_caller_data) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Initilization Error!\n"); switch_core_session_destroy(&session); return FTDM_FAIL; @@ -1604,9 +1631,11 @@ ftdm_status_t ftdm_channel_from_event(ftdm_sigmsg_t *sigmsg, switch_core_session switch_channel_set_variable_printf(channel, "freetdm_chan_number", "%d", chanid); switch_channel_set_variable_printf(channel, "freetdm_bearer_capability", "%d", channel_caller_data->bearer_capability); switch_channel_set_variable_printf(channel, "freetdm_bearer_layer1", "%d", channel_caller_data->bearer_layer1); + switch_channel_set_variable_printf(channel, "freetdm_calling_party_category", ftdm_calling_party_category2str(channel_caller_data->cpc)); switch_channel_set_variable_printf(channel, "screening_ind", ftdm_screening2str(channel_caller_data->screen)); switch_channel_set_variable_printf(channel, "presentation_ind", ftdm_presentation2str(channel_caller_data->pres)); + if (globals.sip_headers) { switch_channel_set_variable(channel, "sip_h_X-FreeTDM-SpanName", ftdm_channel_get_span_name(sigmsg->channel)); switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-SpanNumber", "%d", spanid); @@ -1627,6 +1656,8 @@ ftdm_status_t ftdm_channel_from_event(ftdm_sigmsg_t *sigmsg, switch_core_session switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-RDNIS", "%s", channel_caller_data->rdnis.digits); switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-RDNIS-NADI", "%d", channel_caller_data->rdnis.type); switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-RDNIS-Plan", "%d", channel_caller_data->rdnis.plan); + switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-CPC", "%s", ftdm_calling_party_category2str(channel_caller_data->cpc)); + var_value = ftdm_sigmsg_get_var(sigmsg, "ss7_rdnis_screen_ind"); if (!ftdm_strlen_zero(var_value)) { @@ -1672,7 +1703,12 @@ ftdm_status_t ftdm_channel_from_event(ftdm_sigmsg_t *sigmsg, switch_core_session switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-GN-NumInComp", "%d", var_value); } } /* End - var_value = ftdm_sigmsg_get_var(sigmsg, "ss7_gn_digits"); */ - + + var_value = ftdm_sigmsg_get_var(sigmsg, "ss7_iam"); + if (!ftdm_strlen_zero(var_value)) { + switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-IAM", "%s", var_value); + } + switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-Screen", "%d", channel_caller_data->screen); switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-Presentation", "%d", channel_caller_data->pres); } @@ -1683,7 +1719,12 @@ ftdm_status_t ftdm_channel_from_event(ftdm_sigmsg_t *sigmsg, switch_core_session ftdm_get_current_var(curr, &var_name, &var_value); snprintf(name, sizeof(name), FREETDM_VAR_PREFIX "%s", var_name); switch_channel_set_variable_printf(channel, name, "%s", var_value); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Call Variable: %s = %s\n", name, var_value); + if (!strcasecmp(var_name, "ss7_iam")) { + /* Do not print freetdm_ss7_iam as it is a very long variable */ + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Call Variable: %s is present\n", name); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Call Variable: %s = %s\n", name, var_value); + } } ftdm_iterator_free(iter); @@ -2668,6 +2709,7 @@ static void parse_bri_pri_spans(switch_xml_t cfg, switch_xml_t spans) /* some defaults first */ SPAN_CONFIG[span_id].limit_backend = "hash"; SPAN_CONFIG[span_id].limit_reset_event = FTDM_LIMIT_RESET_ON_TIMEOUT; + SPAN_CONFIG[span_id].digital_sampling_rate = 8000; for (param = switch_xml_child(myspan, "param"); param; param = param->next) { char *var = (char *) switch_xml_attr_soft(param, "name"); @@ -2682,6 +2724,21 @@ static void parse_bri_pri_spans(switch_xml_t cfg, switch_xml_t spans) context = val; } else if (!strcasecmp(var, "dialplan")) { dialplan = val; + } else if (!strcasecmp(var, "unrestricted-digital-codec")) { + //switch_core_strdup(pool, val); + const switch_codec_implementation_t *codec = NULL; + int num_codecs; + num_codecs = switch_loadable_module_get_codecs_sorted(&codec, 1, &val, 1); + if (num_codecs != 1 || !codec) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, + "Failed finding codec %s for unrestricted digital calls\n", val); + } else { + SPAN_CONFIG[span_id].digital_codec = switch_core_strdup(module_pool, codec->iananame); + SPAN_CONFIG[span_id].digital_sampling_rate = codec->samples_per_second; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, + "Unrestricted digital codec is %s at %dhz for span %d\n", + SPAN_CONFIG[span_id].digital_codec, SPAN_CONFIG[span_id].digital_sampling_rate, span_id); + } } else if (!strcasecmp(var, "call_limit_backend")) { SPAN_CONFIG[span_id].limit_backend = val; ftdm_log(FTDM_LOG_DEBUG, "Using limit backend %s for span %d\n", SPAN_CONFIG[span_id].limit_backend, span_id); diff --git a/libs/freetdm/src/ftdm_call_utils.c b/libs/freetdm/src/ftdm_call_utils.c index 2b72f05b77..d23c95af4e 100644 --- a/libs/freetdm/src/ftdm_call_utils.c +++ b/libs/freetdm/src/ftdm_call_utils.c @@ -42,6 +42,74 @@ #include + + +FT_DECLARE(char *) ftdm_url_encode(const char *url, char *buf, ftdm_size_t len) +{ + /* This implementation of url_encode is slightly different compared to the + * Freeswitch one. This is because this implementation accepts the full + * range of values (0x00 - 0xFF) compared to the Freeswitch implementation + * that does not accept 0x00 */ + + const char *p; + size_t x = 0,y = 0; + const char urlunsafe[] = "\r\n \"#%&+:;<=>?@[\\]^`{|}"; + const char hex[] = "0123456789ABCDEF"; + + if (!buf) { + return 0; + } + + if (!url) { + return 0; + } + + len--; + + for (p = url; y <= len; p++) { + if (*p < ' ' || *p > '~' || strchr(urlunsafe, *p)) { + buf[x++] = '%'; + buf[x++] = hex[(*p >> 4) & 0x0f]; + buf[x++] = hex[*p & 0x0f]; + } else { + buf[x++] = *p; + } + y++; + } + buf[x] = '\0'; + return buf; +} + + +FT_DECLARE(char *) ftdm_url_decode(char *s, ftdm_size_t *len) +{ + /* This implementation of url_decode is slightly different compared to the + * Freeswitch one. This is because this implementation accepts the full + * range of values (0x00 - 0xFF) compared to the Freeswitch implementation + * that does not accept 0x00 */ + + char *o; + unsigned int tmp; + ftdm_size_t mylen = 0; + + if (ftdm_strlen_zero(s)) { + return s; + } + + for (o = s; *s; s++, o++) { + if (*s == '%' && strlen(s) > 2 && sscanf(s + 1, "%2x", &tmp) == 1) { + *o = (char) tmp; + s += 2; + } else { + *o = *s; + } + mylen++; + } + *o = '\0'; + *len = mylen; + return s; +} + FT_DECLARE(ftdm_status_t) ftdm_set_npi(const char *string, uint8_t *target) { uint8_t val; diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 1c10171202..b57292c5b0 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -310,21 +310,6 @@ FTDM_STR2ENUM(ftdm_str2channel_indication, ftdm_channel_indication2str, ftdm_cha static ftdm_status_t ftdm_group_add_channels(ftdm_span_t* span, int currindex, const char* name); -static const char *cut_path(const char *in) -{ - const char *p, *ret = in; - char delims[] = "/\\"; - char *i; - - for (i = delims; *i; i++) { - p = in; - while ((p = strchr(p, *i)) != 0) { - ret = ++p; - } - } - return ret; -} - static void null_logger(const char *file, const char *func, int line, int level, const char *fmt, ...) { if (file && func && line && level && fmt) { @@ -350,7 +335,6 @@ static int ftdm_log_level = FTDM_LOG_LEVEL_DEBUG; static void default_logger(const char *file, const char *func, int line, int level, const char *fmt, ...) { - const char *fp; char data[1024]; va_list ap; @@ -360,14 +344,11 @@ static void default_logger(const char *file, const char *func, int line, int lev if (level > ftdm_log_level) { return; } - - fp = cut_path(file); va_start(ap, fmt); vsnprintf(data, sizeof(data), fmt, ap); - fprintf(stderr, "[%s] %s:%d %s() %s", FTDM_LEVEL_NAMES[level], file, line, func, data); va_end(ap); @@ -411,13 +392,13 @@ FT_DECLARE(void) ftdm_set_echocancel_call_begin(ftdm_channel_t *chan) if (ftdm_channel_test_feature(chan, FTDM_CHANNEL_FEATURE_HWEC)) { if (ftdm_channel_test_feature(chan, FTDM_CHANNEL_FEATURE_HWEC_DISABLED_ON_IDLE)) { /* If the ec is disabled on idle, we need to enable it unless is a digital call */ - if (caller_data->bearer_capability != FTDM_BEARER_CAP_64K_UNRESTRICTED) { + if (caller_data->bearer_capability != FTDM_BEARER_CAP_UNRESTRICTED) { ftdm_log_chan(chan, FTDM_LOG_DEBUG, "Enabling ec for call in channel state %s\n", ftdm_channel_state2str(chan->state)); ftdm_channel_command(chan, FTDM_COMMAND_ENABLE_ECHOCANCEL, NULL); } } else { /* If the ec is enabled on idle, we do nothing unless is a digital call that needs it disabled */ - if (caller_data->bearer_capability == FTDM_BEARER_CAP_64K_UNRESTRICTED) { + if (caller_data->bearer_capability == FTDM_BEARER_CAP_UNRESTRICTED) { ftdm_log_chan(chan, FTDM_LOG_DEBUG, "Disabling ec for digital call in channel state %s\n", ftdm_channel_state2str(chan->state)); ftdm_channel_command(chan, FTDM_COMMAND_DISABLE_ECHOCANCEL, NULL); } @@ -508,13 +489,16 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_set_caller_data(ftdm_channel_t *ftdmchan, { ftdm_status_t err = FTDM_SUCCESS; if (!ftdmchan) { - ftdm_log(FTDM_LOG_CRIT, "Error: trying to set caller data, but no ftdmchan!\n"); + ftdm_log(FTDM_LOG_CRIT, "trying to set caller data, but no ftdmchan!\n"); return FTDM_FAIL; } if ((err = ftdm_set_caller_data(ftdmchan->span, caller_data)) != FTDM_SUCCESS) { return err; } ftdmchan->caller_data = *caller_data; + if (ftdmchan->caller_data.bearer_capability == FTDM_BEARER_CAP_UNRESTRICTED) { + ftdm_set_flag(ftdmchan, FTDM_CHANNEL_DIGITAL_MEDIA); + } return FTDM_SUCCESS; } @@ -2628,6 +2612,7 @@ static ftdm_status_t ftdm_channel_done(ftdm_channel_t *ftdmchan) ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_MEDIA); ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_ANSWERED); ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_USER_HANGUP); + ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_DIGITAL_MEDIA); ftdm_mutex_lock(ftdmchan->pre_buffer_mutex); ftdm_buffer_destroy(&ftdmchan->pre_buffer); ftdmchan->pre_buffer_size = 0; @@ -3780,6 +3765,10 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_read(ftdm_channel_t *ftdmchan, void *data handle_tone_generation(ftdmchan); + if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_DIGITAL_MEDIA)) { + goto done; + } + if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_TRANSCODE) && ftdmchan->effective_codec != ftdmchan->native_codec) { if (ftdmchan->native_codec == FTDM_CODEC_ULAW && ftdmchan->effective_codec == FTDM_CODEC_SLIN) { codec_func = fio_ulaw2slin; @@ -3934,7 +3923,7 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_read(ftdm_channel_t *ftdmchan, void *data ftdm_mutex_unlock(ftdmchan->pre_buffer_mutex); - memset(data, 255, *datalen); + memset(data, FTDM_SILENCE_VALUE(ftdmchan), *datalen); if (ftdmchan->skip_read_frames > 0) { ftdmchan->skip_read_frames--; @@ -3946,7 +3935,7 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_read(ftdm_channel_t *ftdmchan, void *data if (ftdm_buffer_inuse(ftdmchan->pre_buffer) >= ftdmchan->pre_buffer_size) { ftdm_buffer_read(ftdmchan->pre_buffer, data, *datalen); } else { - memset(data, 255, *datalen); + memset(data, FTDM_SILENCE_VALUE(ftdmchan), *datalen); } } ftdm_mutex_unlock(ftdmchan->pre_buffer_mutex); @@ -3994,6 +3983,10 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_write(ftdm_channel_t *ftdmchan, void *dat status = FTDM_FAIL; goto done; } + + if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_DIGITAL_MEDIA)) { + goto do_write; + } if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_TRANSCODE) && ftdmchan->effective_codec != ftdmchan->native_codec) { if (ftdmchan->native_codec == FTDM_CODEC_ULAW && ftdmchan->effective_codec == FTDM_CODEC_SLIN) { @@ -4025,6 +4018,8 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_write(ftdm_channel_t *ftdmchan, void *dat } } +do_write: + if (ftdmchan->span->sig_write) { status = ftdmchan->span->sig_write(ftdmchan, data, *datalen); if (status == FTDM_BREAK) { @@ -5374,10 +5369,12 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t ftdm_set_flag(sigmsg->channel, FTDM_CHANNEL_CALL_STARTED); ftdm_call_set_call_id(sigmsg->channel, &sigmsg->channel->caller_data); /* when cleaning up the public API I added this because mod_freetdm.c on_fxs_signal was - * doing it during SIGEVENT_START, but now that flags are private they can't, wonder if - * is needed at all? - * */ + * doing it during SIGEVENT_START, but now that flags are private they can't, wonder if + * is needed at all? */ ftdm_clear_flag(sigmsg->channel, FTDM_CHANNEL_HOLD); + if (sigmsg->channel->caller_data.bearer_capability == FTDM_BEARER_CAP_UNRESTRICTED) { + ftdm_set_flag(sigmsg->channel, FTDM_CHANNEL_DIGITAL_MEDIA); + } } break; diff --git a/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.c b/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.c index 21008e6c96..7e230ecc34 100644 --- a/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.c +++ b/libs/freetdm/src/ftmod/ftmod_analog/ftmod_analog.c @@ -426,7 +426,6 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj) uint32_t state_counter = 0, elapsed = 0, collecting = 0, interval = 0, last_digit = 0, indicate = 0, dial_timeout = analog_data->wait_dialtone_timeout; uint32_t answer_on_polarity_counter = 0; ftdm_sigmsg_t sig; - ftdm_status_t status; ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "ANALOG CHANNEL thread starting.\n"); @@ -916,7 +915,7 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj) } if (codec_func) { - status = codec_func(frame, sizeof(frame), &rlen); + codec_func(frame, sizeof(frame), &rlen); } else { snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "codec error!"); goto done; diff --git a/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.c b/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.c index 31c2421b9b..907a8cb034 100644 --- a/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.c +++ b/libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.c @@ -221,7 +221,6 @@ static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj) ftdm_channel_t *closed_chan; uint32_t state_counter = 0, elapsed = 0, collecting = 0, interval = 0, last_digit = 0, indicate = 0, dial_timeout = 30000; ftdm_sigmsg_t sig; - ftdm_status_t status; ftdm_log(FTDM_LOG_DEBUG, "ANALOG EM CHANNEL thread starting.\n"); @@ -545,7 +544,7 @@ static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj) } if (codec_func) { - status = codec_func(frame, sizeof(frame), &rlen); + codec_func(frame, sizeof(frame), &rlen); } else { snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "codec error!"); goto done; diff --git a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c index ec7fe39c7d..8093443986 100644 --- a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c +++ b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c @@ -1965,6 +1965,10 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_libpri_configure_span) assert(isdn_data != NULL); memset(isdn_data, 0, sizeof(*isdn_data)); + /* set some default values */ + isdn_data->mode = PRI_CPE; + isdn_data->ton = PRI_UNKNOWN; + switch (ftdm_span_get_trunk_type(span)) { case FTDM_TRUNK_BRI: case FTDM_TRUNK_BRI_PTMP: @@ -1975,12 +1979,14 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_libpri_configure_span) #endif case FTDM_TRUNK_E1: ftdm_log(FTDM_LOG_NOTICE, "Setting default Layer 1 to ALAW since this is an E1/BRI/BRI PTMP trunk\n"); - isdn_data->layer1 = PRI_LAYER_1_ALAW; + isdn_data->layer1 = PRI_LAYER_1_ALAW; + isdn_data->dialect = PRI_SWITCH_EUROISDN_E1; break; case FTDM_TRUNK_T1: case FTDM_TRUNK_J1: ftdm_log(FTDM_LOG_NOTICE, "Setting default Layer 1 to ULAW since this is a T1/J1 trunk\n"); - isdn_data->layer1 = PRI_LAYER_1_ULAW; + isdn_data->layer1 = PRI_LAYER_1_ULAW; + isdn_data->dialect = PRI_SWITCH_LUCENT5E; break; default: ftdm_log(FTDM_LOG_ERROR, "Invalid trunk type: '%s'\n", ftdm_span_get_trunk_type_str(span)); diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h index 902729d01c..ac69fa8d66 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h @@ -292,6 +292,12 @@ typedef struct ftdm_sngisdn_data { sngisdn_span_data_t *spans[MAX_L1_LINKS+1]; /* spans are indexed by link_id */ }ftdm_sngisdn_data_t; +typedef struct ftdm2trillium +{ + uint8_t ftdm_val; + uint8_t trillium_val; +}ftdm2trillium_t; + /* TODO implement these 2 functions */ #define ISDN_FUNC_TRACE_ENTER(a) diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c index 1bd2753e81..88aa9131b6 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c @@ -745,8 +745,16 @@ ftdm_status_t sngisdn_stack_cfg_q931_dlsap(ftdm_span_t *span) /* TODO: Fill in these timers with proper values - eventually pass them */ cfg.t.cfg.s.inDLSAP.tmr.t301.enb = TRUE; cfg.t.cfg.s.inDLSAP.tmr.t301.val = 180; - cfg.t.cfg.s.inDLSAP.tmr.t302.enb = TRUE; - cfg.t.cfg.s.inDLSAP.tmr.t302.val = 15; + + /* It looks like ETSI is the only variant that supports Overlap */ + if (signal_data->switchtype == SNGISDN_SWITCH_EUROISDN) { + cfg.t.cfg.s.inDLSAP.tmr.t302.enb = TRUE; + cfg.t.cfg.s.inDLSAP.tmr.t302.val = 15; + } else { + cfg.t.cfg.s.inDLSAP.tmr.t302.enb = FALSE; + cfg.t.cfg.s.inDLSAP.tmr.t302.val = 0; + } + cfg.t.cfg.s.inDLSAP.tmr.t303.enb = TRUE; cfg.t.cfg.s.inDLSAP.tmr.t303.val = 4; cfg.t.cfg.s.inDLSAP.tmr.t304.enb = TRUE; 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 b1af8a61c3..0789c433f9 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 @@ -831,7 +831,7 @@ void sngisdn_process_fac_ind (sngisdn_event_data_t *sngisdn_event) if (sng_isdn_retrieve_facility_caller_name(&facEvnt->facElmt.facStr.val[2], facEvnt->facElmt.facStr.len, retrieved_str) == 0) { strcpy(ftdmchan->caller_data.cid_name, retrieved_str); } else { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Failed to retrieve Caller Name from Facility IE\n"); + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Failed to retrieve Caller Name from Facility IE\n"); } if (signal_data->facility_timeout) { /* Cancel facility timeout */ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c index 7b9989dd4c..67de893f5d 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c @@ -779,7 +779,6 @@ void sngisdn_rcv_cc_ind(CcMngmt *status) void sngisdn_rcv_q931_trace(InMngmt *trc, Buffer *mBuf) { MsgLen mlen; - MsgLen i; int16_t j; Buffer *tmp; Data *cptr; @@ -802,7 +801,6 @@ void sngisdn_rcv_q931_trace(InMngmt *trc, Buffer *mBuf) tmp = mBuf->b_cont; cptr = tmp->b_rptr; data = *cptr++; - i = 0; for(j=0;jftdm_val == ftdm_val) { + return val->trillium_val; + } + } + return default_val; +} + +static uint8_t get_ftdm_val(ftdm2trillium_t *vals, uint8_t trillium_val, uint8_t default_val) +{ + ftdm2trillium_t *val = vals; + while(val++) { + if (val->trillium_val == trillium_val) { + return val->ftdm_val; + } + } + return default_val; +} + + void clear_call_data(sngisdn_chan_data_t *sngisdn_info) { uint32_t cc_id = ((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->cc_id; @@ -257,11 +303,11 @@ ftdm_status_t get_called_num(ftdm_channel_t *ftdmchan, CdPtyNmb *cdPtyNmb) } if (cdPtyNmb->nmbPlanId.pres == PRSNT_NODEF) { - caller_data->dnis.plan = cdPtyNmb->nmbPlanId.val; + caller_data->dnis.plan = get_ftdm_val(npi_codes, cdPtyNmb->nmbPlanId.val, IN_NP_UNK); } if (cdPtyNmb->typeNmb0.pres == PRSNT_NODEF) { - caller_data->dnis.type = cdPtyNmb->typeNmb0.val; + caller_data->dnis.type = get_ftdm_val(ton_codes, cdPtyNmb->typeNmb0.val, IN_TON_UNK); } if (cdPtyNmb->nmbDigits.pres == PRSNT_NODEF) { @@ -281,11 +327,11 @@ ftdm_status_t get_redir_num(ftdm_channel_t *ftdmchan, RedirNmb *redirNmb) } if (redirNmb->nmbPlanId.pres == PRSNT_NODEF) { - caller_data->rdnis.plan = redirNmb->nmbPlanId.val; + caller_data->rdnis.plan = get_ftdm_val(npi_codes, redirNmb->nmbPlanId.val, IN_NP_UNK); } if (redirNmb->typeNmb.pres == PRSNT_NODEF) { - caller_data->rdnis.type = redirNmb->typeNmb.val; + caller_data->rdnis.type = get_ftdm_val(ton_codes, redirNmb->typeNmb.val, IN_TON_UNK); } if (redirNmb->nmbDigits.pres == PRSNT_NODEF) { @@ -380,11 +426,13 @@ ftdm_status_t get_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, uint8 ftdm_status_t get_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd) { uint8_t val; + if (!progInd->eh.pres) { return FTDM_FAIL; } if (progInd->progDesc.pres) { + /* TODO: use get_ftdm_val function and table here */ switch (progInd->progDesc.val) { case IN_PD_NOTETEISDN: val = SNGISDN_PROGIND_DESCR_NETE_ISDN; @@ -462,19 +510,11 @@ ftdm_status_t set_calling_num(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb) cgPtyNmb->presInd0.val = caller_data->pres; cgPtyNmb->nmbPlanId.pres = PRSNT_NODEF; - if (caller_data->cid_num.plan >= FTDM_NPI_INVALID) { - cgPtyNmb->nmbPlanId.val = FTDM_NPI_UNKNOWN; - } else { - cgPtyNmb->nmbPlanId.val = caller_data->cid_num.plan; - } + cgPtyNmb->nmbPlanId.val = get_trillium_val(npi_codes, caller_data->cid_num.plan, IN_NP_UNK); cgPtyNmb->typeNmb1.pres = PRSNT_NODEF; - if (caller_data->cid_num.type >= FTDM_TON_INVALID) { - cgPtyNmb->typeNmb1.val = FTDM_TON_UNKNOWN; - } else { - cgPtyNmb->typeNmb1.val = caller_data->cid_num.type; - } + cgPtyNmb->typeNmb1.val = get_trillium_val(ton_codes, caller_data->cid_num.type, IN_TON_UNK); cgPtyNmb->nmbDigits.pres = PRSNT_NODEF; cgPtyNmb->nmbDigits.len = len; @@ -508,7 +548,7 @@ ftdm_status_t set_calling_num2(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb) val = FTDM_SCREENING_INVALID; string = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "isdn.cg_pty2.screening_ind"); - if ((string != NULL) && (*string)) { + if (!ftdm_strlen_zero(string)) { val = ftdm_str2ftdm_screening(string); } @@ -525,7 +565,7 @@ ftdm_status_t set_calling_num2(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb) val = FTDM_PRES_INVALID; string = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "isdn.cg_pty2.presentation_ind"); - if ((string != NULL) && (*string)) { + if (!ftdm_strlen_zero(string)) { val = ftdm_str2ftdm_presentation(string); } @@ -540,14 +580,14 @@ ftdm_status_t set_calling_num2(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb) val = FTDM_NPI_INVALID; string = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "isdn.cg_pty2.npi"); - if ((string != NULL) && (*string)) { + if (!ftdm_strlen_zero(string)) { val = ftdm_str2ftdm_npi(string); } if (val == FTDM_NPI_INVALID) { cgPtyNmb->nmbPlanId.val = caller_data->cid_num.plan; } else { - cgPtyNmb->nmbPlanId.val = val; + cgPtyNmb->nmbPlanId.val = get_trillium_val(npi_codes, val, IN_NP_UNK); } cgPtyNmb->typeNmb1.pres = PRSNT_NODEF; @@ -555,14 +595,14 @@ ftdm_status_t set_calling_num2(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb) /* Type of Number */ val = FTDM_TON_INVALID; string = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "isdn.cg_pty2.ton"); - if ((string != NULL) && (*string)) { + if (!ftdm_strlen_zero(string)) { val = ftdm_str2ftdm_ton(string); } if (val == FTDM_TON_INVALID) { cgPtyNmb->typeNmb1.val = caller_data->cid_num.type; } else { - cgPtyNmb->typeNmb1.val = val; + cgPtyNmb->typeNmb1.val = get_trillium_val(ton_codes, val, IN_TON_UNK); } return FTDM_SUCCESS; } @@ -575,21 +615,14 @@ ftdm_status_t set_called_num(ftdm_channel_t *ftdmchan, CdPtyNmb *cdPtyNmb) if (!len) { return FTDM_SUCCESS; } - cdPtyNmb->eh.pres = PRSNT_NODEF; - - cdPtyNmb->nmbPlanId.pres = PRSNT_NODEF; - if (caller_data->dnis.plan >= FTDM_NPI_INVALID) { - cdPtyNmb->nmbPlanId.val = FTDM_NPI_UNKNOWN; - } else { - cdPtyNmb->nmbPlanId.val = caller_data->dnis.plan; - } - cdPtyNmb->typeNmb0.pres = PRSNT_NODEF; - if (caller_data->dnis.type >= FTDM_TON_INVALID) { - cdPtyNmb->typeNmb0.val = FTDM_TON_UNKNOWN; - } else { - cdPtyNmb->typeNmb0.val = caller_data->dnis.type; - } + cdPtyNmb->eh.pres = PRSNT_NODEF; + + cdPtyNmb->nmbPlanId.pres = PRSNT_NODEF; + cdPtyNmb->nmbPlanId.val = get_trillium_val(npi_codes, caller_data->dnis.plan, IN_NP_UNK); + + cdPtyNmb->typeNmb0.pres = PRSNT_NODEF; + cdPtyNmb->typeNmb0.val = get_trillium_val(ton_codes, caller_data->dnis.type, IN_TON_UNK); cdPtyNmb->nmbDigits.pres = PRSNT_NODEF; cdPtyNmb->nmbDigits.len = len; @@ -610,18 +643,10 @@ ftdm_status_t set_redir_num(ftdm_channel_t *ftdmchan, RedirNmb *redirNmb) redirNmb->eh.pres = PRSNT_NODEF; redirNmb->nmbPlanId.pres = PRSNT_NODEF; - if (caller_data->rdnis.plan >= FTDM_NPI_INVALID) { - redirNmb->nmbPlanId.val = FTDM_NPI_UNKNOWN; - } else { - redirNmb->nmbPlanId.val = caller_data->rdnis.plan; - } + redirNmb->nmbPlanId.val = get_trillium_val(npi_codes, caller_data->rdnis.plan, IN_NP_UNK); redirNmb->typeNmb.pres = PRSNT_NODEF; - if (caller_data->rdnis.type >= FTDM_TON_INVALID) { - redirNmb->typeNmb.val = FTDM_TON_UNKNOWN; - } else { - redirNmb->typeNmb.val = caller_data->rdnis.type; - } + redirNmb->typeNmb.val = get_trillium_val(ton_codes, caller_data->rdnis.type, IN_TON_UNK); redirNmb->nmbDigits.pres = PRSNT_NODEF; redirNmb->nmbDigits.len = len; @@ -741,7 +766,7 @@ ftdm_status_t set_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd, ftdm_s int loc = prog_ind.loc; str = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "isdn.prog_ind.descr"); - if (str && *str) { + if (!ftdm_strlen_zero(str)) { /* User wants to override progress indicator */ descr = ftdm_str2ftdm_sngisdn_progind_descr(str); } @@ -752,7 +777,7 @@ ftdm_status_t set_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd, ftdm_s } str = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "isdn.prog_ind.loc"); - if (str && *str) { + if (!ftdm_strlen_zero(str)) { loc = ftdm_str2ftdm_sngisdn_progind_loc(str); } if (loc == SNGISDN_PROGIND_LOC_INVALID) { @@ -1067,18 +1092,20 @@ void get_memory_info(void) return; } + uint8_t sngisdn_get_infoTranCap_from_user(ftdm_bearer_cap_t bearer_capability) { switch(bearer_capability) { case FTDM_BEARER_CAP_SPEECH: return IN_ITC_SPEECH; - case FTDM_BEARER_CAP_64K_UNRESTRICTED: + case FTDM_BEARER_CAP_UNRESTRICTED: return IN_ITC_UNRDIG; case FTDM_BEARER_CAP_3_1KHZ_AUDIO: return IN_ITC_A31KHZ; case FTDM_BEARER_CAP_INVALID: return IN_ITC_SPEECH; - /* Do not put a default case here, so we can see compile warnings if we have unhandled cases */ + default: + return IN_ITC_SPEECH; } return FTDM_BEARER_CAP_SPEECH; } @@ -1094,7 +1121,8 @@ uint8_t sngisdn_get_usrInfoLyr1Prot_from_user(ftdm_user_layer1_prot_t layer1_pro return IN_UIL1_G711ALAW; case FTDM_USER_LAYER1_PROT_INVALID: return IN_UIL1_G711ULAW; - /* Do not put a default case here, so we can see compile warnings if we have unhandled cases */ + default: + return IN_UIL1_G711ULAW; } return IN_UIL1_G711ULAW; } @@ -1103,9 +1131,9 @@ ftdm_bearer_cap_t sngisdn_get_infoTranCap_from_stack(uint8_t bearer_capability) { switch(bearer_capability) { case IN_ITC_SPEECH: - return FTDM_BEARER_CAP_SPEECH; + return FTDM_BEARER_CAP_SPEECH; case IN_ITC_UNRDIG: - return FTDM_BEARER_CAP_64K_UNRESTRICTED; + return FTDM_BEARER_CAP_UNRESTRICTED; case IN_ITC_A31KHZ: return FTDM_BEARER_CAP_3_1KHZ_AUDIO; default: diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.c index 8c8c8d5159..d455fc06d0 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.c @@ -334,11 +334,12 @@ uint32_t sngisdn_decode_ie(char *str, uint32_t *str_len, uint8_t current_codeset switch(ieId) { case PROT_Q931_IE_BEARER_CAP: { - uint8_t codingStandard, infTransferCap, transferMode, infTransferRate, usrL1Prot; + uint8_t codingStandard, infTransferCap, infTransferRate, usrL1Prot; + /*uint8_t transferMode;*/ codingStandard = get_bits(OCTET(3),6,7); infTransferCap = get_bits(OCTET(3),1,5); - transferMode = get_bits(OCTET(4),6,7); + /*transferMode = get_bits(OCTET(4),6,7);*/ infTransferRate = get_bits(OCTET(4),1,5); usrL1Prot = get_bits(OCTET(5),1,5); @@ -404,8 +405,9 @@ uint32_t sngisdn_decode_ie(char *str, uint32_t *str_len, uint8_t current_codeset uint8_t infoChannelSelection=0; uint8_t prefExclusive=0; uint8_t ifaceIdPresent=0; - uint8_t ifaceIdentifier = 0; /* octet_3_1 */ - uint8_t chanType=0, numberMap=0, codingStandard=0; + /* uint8_t ifaceIdentifier = 0; */ /* octet_3_1 */ + uint8_t chanType=0, numberMap=0; + /* uint8_t codingStandard=0; */ uint8_t channelNo = 0; infoChannelSelection = get_bits(OCTET(3),1,2); @@ -413,15 +415,15 @@ uint32_t sngisdn_decode_ie(char *str, uint32_t *str_len, uint8_t current_codeset ifaceIdPresent = get_bits(OCTET(3),7,7); if (ifaceIdPresent) { - ifaceIdentifier= get_bits(OCTET(4),1,7); + /*ifaceIdentifier= get_bits(OCTET(4),1,7);*/ chanType = get_bits(OCTET(5),1,4); numberMap = get_bits(OCTET(5),5,5); - codingStandard = get_bits(OCTET(5),6,7); + /*codingStandard = get_bits(OCTET(5),6,7);*/ channelNo = get_bits(OCTET(6),1,7); } else { chanType = get_bits(OCTET(4),1,4); numberMap = get_bits(OCTET(4),5,5); - codingStandard = get_bits(OCTET(4),6,7); + /*codingStandard = get_bits(OCTET(4),6,7);*/ channelNo = get_bits(OCTET(5),1,7); } diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c index 3348292935..0520e9d163 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c @@ -33,12 +33,14 @@ /* INCLUDE ********************************************************************/ #include "ftmod_sangoma_ss7_main.h" + /******************************************************************************/ /* DEFINES ********************************************************************/ /******************************************************************************/ /* GLOBALS ********************************************************************/ + /******************************************************************************/ /* PROTOTYPES *****************************************************************/ @@ -79,14 +81,14 @@ ftdm_status_t handle_olm_msg(uint32_t suInstId, uint32_t spInstId, uint32_t circ /******************************************************************************/ /* FUNCTIONS ******************************************************************/ + ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiConEvnt *siConEvnt) { - SS7_FUNC_TRACE_ENTER(__FUNCTION__); - sngss7_chan_data_t *sngss7_info = NULL; ftdm_channel_t *ftdmchan = NULL; char nadi[2]; - + + SS7_FUNC_TRACE_ENTER(__FUNCTION__); memset(nadi, '\0', sizeof(nadi)); /* get the ftdmchan and ss7_chan_data from the circuit */ @@ -189,6 +191,8 @@ ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ copy_genNmb_from_sngss7(ftdmchan, &siConEvnt->genNmb); + copy_cgPtyCat_from_sngss7(ftdmchan, &siConEvnt->cgPtyCat); + /* fill in the TMR/bearer capability */ if (siConEvnt->txMedReq.eh.pres) { if (siConEvnt->txMedReq.trMedReq.pres) { @@ -206,6 +210,10 @@ ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ sprintf(nadi, "%d", siConEvnt->cdPtyNum.natAddrInd.val); sngss7_add_var(sngss7_info, "ss7_cld_nadi", nadi); + if (sngss7_info->circuit->transparent_iam) { + sngss7_save_iam(ftdmchan, siConEvnt); + } + /* check if a COT test is requested */ if ((siConEvnt->natConInd.eh.pres) && (siConEvnt->natConInd.contChkInd.pres) && @@ -229,7 +237,6 @@ ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ siConEvnt->cgPtyNum.natAddrInd.val, ftdmchan->caller_data.dnis.digits, siConEvnt->cdPtyNum.natAddrInd.val); - } /* if (channel is usable */ break; diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c index 59660765a1..53062b9d56 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c @@ -42,6 +42,7 @@ static sng_isup_event_interface_t sng_event; static ftdm_io_interface_t g_ftdm_sngss7_interface; ftdm_sngss7_data_t g_ftdm_sngss7_data; + /******************************************************************************/ /* PROTOTYPES *****************************************************************/ @@ -509,11 +510,6 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) SS7_DEBUG_CHAN(ftdmchan, "ftmod_sangoma_ss7 processing state %s\n", ftdm_channel_state2str (ftdmchan->state)); -#if 0 - /* clear the state change flag...since we might be setting a new state */ - ftdm_channel_complete_state(ftdmchan); -#endif - /*check what state we are supposed to be in */ switch (ftdmchan->state) { /**************************************************************************/ @@ -674,9 +670,6 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) } else { /*INBOUND...so FS told us it was going to answer...tell the stack */ ft_to_sngss7_anm(ftdmchan); -#if 1 /* DAVIDY */ - ft_to_sngss7_itx(ftdmchan); -#endif } break; diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h index a355ee0ee7..f88202b1a8 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h @@ -60,6 +60,13 @@ #define MAX_SIZEOF_SUBADDR_IE 24 /* as per Q931 4.5.9 */ +typedef struct ftdm2trillium +{ + uint8_t ftdm_val; + uint8_t trillium_val; +}ftdm2trillium_t; + + typedef enum { SNGSS7_CON_IND_EVENT = 0, SNGSS7_CON_CFM_EVENT, @@ -332,6 +339,7 @@ typedef struct sng_isup_ckt { uint32_t min_digits; uint8_t itx_auto_reply; + uint8_t transparent_iam; void *obj; uint16_t t3; uint16_t t12; @@ -399,6 +407,7 @@ typedef struct sng_ss7_cfg { uint32_t procId; char license[MAX_PATH]; char signature[MAX_PATH]; + uint32_t transparent_iam_max_size; uint32_t flags; sng_relay_t relay[MAX_RELAY_CHANNELS+1]; sng_mtp1_link_t mtp1Link[MAX_MTP_LINKS+1]; @@ -758,6 +767,10 @@ void sngss7_resm_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiR void sngss7_susp_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiSuspEvnt *siSuspEvnt); void sngss7_ssp_sta_cfm(uint32_t infId); +ftdm_status_t sngss7_bufferzero_iam(SiConEvnt *siConEvnt); +ftdm_status_t sngss7_retrieve_iam(ftdm_channel_t *ftdmchan, SiConEvnt *siConEvnt); +ftdm_status_t sngss7_save_iam(ftdm_channel_t *ftdmchan, SiConEvnt *siConEvnt); + /* in ftmod_sangoma_ss7_handle.c */ ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiConEvnt *siConEvnt); ftdm_status_t handle_con_sta(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiCnStEvnt *siCnStEvnt, uint8_t evntType); @@ -806,6 +819,13 @@ ftdm_status_t copy_redirgNum_to_sngss7(ftdm_channel_t *ftdmchan, SiRedirNum *red ftdm_status_t copy_redirgNum_from_sngss7(ftdm_channel_t *ftdmchan, SiRedirNum *redirgNum); ftdm_status_t copy_genNmb_to_sngss7(ftdm_channel_t *ftdmchan, SiGenNum *genNmb); ftdm_status_t copy_genNmb_from_sngss7(ftdm_channel_t *ftdmchan, SiGenNum *genNmb); +ftdm_status_t copy_cgPtyCat_to_sngss7(ftdm_channel_t *ftdmchan, SiCgPtyCat *cgPtyCat); +ftdm_status_t copy_cgPtyCat_from_sngss7(ftdm_channel_t *ftdmchan, SiCgPtyCat *cgPtyCat); +ftdm_status_t copy_accTrnspt_to_sngss7(ftdm_channel_t *ftdmchan, SiAccTrnspt *accTrnspt); +ftdm_status_t copy_natConInd_to_sngss7(ftdm_channel_t *ftdmchan, SiNatConInd *natConInd); +ftdm_status_t copy_fwdCallInd_to_sngss7(ftdm_channel_t *ftdmchan, SiFwdCallInd *fwdCallInd); +ftdm_status_t copy_txMedReq_to_sngss7(ftdm_channel_t *ftdmchan, SiTxMedReq *txMedReq); +ftdm_status_t copy_usrServInfoA_to_sngss7(ftdm_channel_t *ftdmchan, SiUsrServInfo *usrServInfoA); ftdm_status_t copy_tknStr_from_sngss7(TknStr str, char *ftdm, TknU8 oddEven); ftdm_status_t append_tknStr_from_sngss7(TknStr str, char *ftdm, TknU8 oddEven); diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c index a746301cd7..91b8900fef 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c @@ -36,10 +36,8 @@ /******************************************************************************/ /* DEFINES ********************************************************************/ -/******************************************************************************/ /* GLOBALS ********************************************************************/ -/******************************************************************************/ /* PROTOTYPES *****************************************************************/ void ft_to_sngss7_iam(ftdm_channel_t * ftdmchan); @@ -66,221 +64,70 @@ void ft_to_sngss7_cgu(ftdm_channel_t * ftdmchan); void ft_to_sngss7_cgba(ftdm_channel_t * ftdmchan); void ft_to_sngss7_cgua(ftdm_channel_t * ftdmchan); -/******************************************************************************/ /* FUNCTIONS ******************************************************************/ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan) -{ - SS7_FUNC_TRACE_ENTER (__FUNCTION__); - - sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;; - const char *clg_subAddr = NULL; - const char *cld_subAddr = NULL; - char subAddrIE[MAX_SIZEOF_SUBADDR_IE]; +{ SiConEvnt iam; + sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;; + + SS7_FUNC_TRACE_ENTER (__FUNCTION__); sngss7_info->suInstId = get_unique_id (); sngss7_info->spInstId = 0; sngss7_info->spId = 1; memset (&iam, 0x0, sizeof (iam)); - - /* copy down the nature of connection indicators */ - iam.natConInd.eh.pres = PRSNT_NODEF; - iam.natConInd.satInd.pres = PRSNT_NODEF; - iam.natConInd.satInd.val = 0; /* no satellite circuit */ - iam.natConInd.contChkInd.pres = PRSNT_NODEF; - iam.natConInd.contChkInd.val = CONTCHK_NOTREQ; - iam.natConInd.echoCntrlDevInd.pres = PRSNT_NODEF; - iam.natConInd.echoCntrlDevInd.val = ECHOCDEV_INCL; - - /* copy down the forward call indicators */ - iam.fwdCallInd.eh.pres = PRSNT_NODEF; - iam.fwdCallInd.natIntCallInd.pres = PRSNT_NODEF; - iam.fwdCallInd.natIntCallInd.val = 0x00; - iam.fwdCallInd.end2EndMethInd.pres = PRSNT_NODEF; - iam.fwdCallInd.end2EndMethInd.val = E2EMTH_NOMETH; - iam.fwdCallInd.intInd.pres = PRSNT_NODEF; - iam.fwdCallInd.intInd.val = INTIND_NOINTW; - iam.fwdCallInd.end2EndInfoInd.pres = PRSNT_NODEF; - iam.fwdCallInd.end2EndInfoInd.val = E2EINF_NOINFO; - iam.fwdCallInd.isdnUsrPrtInd.pres = PRSNT_NODEF; - iam.fwdCallInd.isdnUsrPrtInd.val = ISUP_USED; - iam.fwdCallInd.isdnUsrPrtPrfInd.pres = PRSNT_NODEF; - iam.fwdCallInd.isdnUsrPrtPrfInd.val = PREF_PREFAW; - iam.fwdCallInd.isdnAccInd.pres = PRSNT_NODEF; - iam.fwdCallInd.isdnAccInd.val = ISDNACC_ISDN; - iam.fwdCallInd.sccpMethInd.pres = PRSNT_NODEF; - iam.fwdCallInd.sccpMethInd.val = SCCPMTH_NOIND; - - /* copy down the calling number information */ - iam.cgPtyCat.eh.pres = PRSNT_NODEF; - iam.cgPtyCat.cgPtyCat.pres = PRSNT_NODEF; - iam.cgPtyCat.cgPtyCat.val = CAT_ORD; /* ordinary suscriber */ - - /* copy down the transmission medium requirements */ - iam.txMedReq.eh.pres = PRSNT_NODEF; - iam.txMedReq.trMedReq.pres = PRSNT_NODEF; - iam.txMedReq.trMedReq.val = ftdmchan->caller_data.bearer_capability; - if ((g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].switchType == LSI_SW_ANS88) || - (g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].switchType == LSI_SW_ANS92) || - (g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].switchType == LSI_SW_ANS95)) { + if (sngss7_info->circuit->transparent_iam && + sngss7_retrieve_iam(ftdmchan, &iam) == FTDM_SUCCESS) { + SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx IAM (Transparent)\n", sngss7_info->circuit->cic); + } else { + /* Nature of Connection Indicators */ + copy_natConInd_to_sngss7(ftdmchan, &iam.natConInd); - /* include only if we're running ANSI */ - iam.fwdCallInd.transCallNInd.pres = PRSNT_NODEF; - iam.fwdCallInd.transCallNInd.val = 0x0; + /* Forward Call Indicators */ + copy_fwdCallInd_to_sngss7(ftdmchan, &iam.fwdCallInd); - iam.usrServInfoA.eh.pres = PRSNT_NODEF; + /* Transmission medium requirements */ + copy_txMedReq_to_sngss7(ftdmchan, &iam.txMedReq); - iam.usrServInfoA.infoTranCap.pres = PRSNT_NODEF; - switch (ftdmchan->caller_data.bearer_capability) { - /**********************************************************************/ - case (FTDM_BEARER_CAP_SPEECH): - iam.usrServInfoA.infoTranCap.val = 0x0; /* speech as per ATIS-1000113.3.2005 */ - break; - /**********************************************************************/ - case (FTDM_BEARER_CAP_64K_UNRESTRICTED): - iam.usrServInfoA.infoTranCap.val = 0x8; /* unrestricted digital as per ATIS-1000113.3.2005 */ - break; - /**********************************************************************/ - case (FTDM_BEARER_CAP_3_1KHZ_AUDIO): - iam.usrServInfoA.infoTranCap.val = 0x10; /* 3.1kHz audio as per ATIS-1000113.3.2005 */ - break; - /**********************************************************************/ - default: - SS7_ERROR_CHAN(ftdmchan, "Unknown Bearer capability falling back to speech%s\n", " "); - iam.usrServInfoA.infoTranCap.val = 0x0; /* speech as per ATIS-1000113.3.2005 */ - break; - /**********************************************************************/ - } /* switch (ftdmchan->caller_data.bearer_capability) */ - - iam.usrServInfoA.cdeStand.pres = PRSNT_NODEF; - iam.usrServInfoA.cdeStand.val = 0x0; /* ITU-T standardized coding */ - iam.usrServInfoA.tranMode.pres = PRSNT_NODEF; - iam.usrServInfoA.tranMode.val = 0x0; /* circuit mode */ - iam.usrServInfoA.infoTranRate0.pres = PRSNT_NODEF; - iam.usrServInfoA.infoTranRate0.val = 0x10; /* 64kbps origination to destination */ - iam.usrServInfoA.infoTranRate1.pres = PRSNT_NODEF; - iam.usrServInfoA.infoTranRate1.val = 0x10; /* 64kbps destination to origination */ - iam.usrServInfoA.chanStruct.pres = PRSNT_NODEF; - iam.usrServInfoA.chanStruct.val = 0x1; /* 8kHz integrity */ - iam.usrServInfoA.config.pres = PRSNT_NODEF; - iam.usrServInfoA.config.val = 0x0; /* point to point configuration */ - iam.usrServInfoA.establish.pres = PRSNT_NODEF; - iam.usrServInfoA.establish.val = 0x0; /* on demand */ - iam.usrServInfoA.symmetry.pres = PRSNT_NODEF; - iam.usrServInfoA.symmetry.val = 0x0; /* bi-directional symmetric */ - iam.usrServInfoA.usrInfLyr1Prot.pres = PRSNT_NODEF; - iam.usrServInfoA.usrInfLyr1Prot.val = 0x2; /* G.711 ulaw */ - iam.usrServInfoA.rateMultiplier.pres = PRSNT_NODEF; - iam.usrServInfoA.rateMultiplier.val = 0x1; /* 1x rate multipler */ - } /* if ANSI */ - - /* copy down the called number information */ - copy_cdPtyNum_to_sngss7 (ftdmchan, &iam.cdPtyNum); - - /* copy down the calling number information */ - copy_cgPtyNum_to_sngss7 (ftdmchan, &iam.cgPtyNum); - - /* copy down the generic number information */ - copy_genNmb_to_sngss7(ftdmchan, &iam.genNmb); - - /* TODO - move this to copy_clg_subAddr_to_sngss7 function */ - /* check if the user would like us to send a clg_sub-address */ - clg_subAddr = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_clg_subaddr"); - if (!ftdm_strlen_zero(clg_subAddr)) { - SS7_DEBUG_CHAN(ftdmchan,"Found user supplied Calling Sub-Address value \"%s\"\n", clg_subAddr); + /* User Service Info A */ + copy_usrServInfoA_to_sngss7(ftdmchan, &iam.usrServInfoA); - /* clean out the subAddrIE */ - memset(subAddrIE, 0x0, sizeof(subAddrIE)); + /* Called Number information */ + copy_cdPtyNum_to_sngss7(ftdmchan, &iam.cdPtyNum); + + /* Calling Number information */ + copy_cgPtyNum_to_sngss7(ftdmchan, &iam.cgPtyNum); - /* check the first character in the sub-address to see what type of encoding to use */ - switch (clg_subAddr[0]) { - case '0': /* NSAP */ - encode_subAddrIE_nsap(&clg_subAddr[1], subAddrIE, SNG_CALLING); - break; - case '1': /* national variant */ - encode_subAddrIE_nat(&clg_subAddr[1], subAddrIE, SNG_CALLING); - break; - default: - SS7_ERROR_CHAN(ftdmchan,"Invalid Calling Sub-Address encoding requested: %c\n", clg_subAddr[0]); - break; - } /* switch (cld_subAddr[0]) */ + /* Generic Number information */ + copy_genNmb_to_sngss7(ftdmchan, &iam.genNmb); + /* Calling Party's Category */ + copy_cgPtyCat_to_sngss7(ftdmchan, &iam.cgPtyCat); - /* if subaddIE is still empty don't copy it in */ - if (subAddrIE[0] != '0') { - /* check if the clg_subAddr has already been added */ - if (iam.accTrnspt.eh.pres == PRSNT_NODEF) { - /* append the subAddrIE */ - memcpy(&iam.accTrnspt.infoElmts.val[iam.accTrnspt.infoElmts.len], subAddrIE, (subAddrIE[1] + 2)); - iam.accTrnspt.infoElmts.len = iam.accTrnspt.infoElmts.len +subAddrIE[1] + 2; - } else { - /* fill in from the beginning */ - iam.accTrnspt.eh.pres = PRSNT_NODEF; - iam.accTrnspt.infoElmts.pres = PRSNT_NODEF; - memcpy(iam.accTrnspt.infoElmts.val, subAddrIE, (subAddrIE[1] + 2)); - iam.accTrnspt.infoElmts.len = subAddrIE[1] + 2; - } /* if (iam.accTrnspt.eh.pres */ - } /* if (subAddrIE[0] != '0') */ + /* Redirecting Number */ + copy_redirgNum_to_sngss7(ftdmchan, &iam.redirgNum); + + /* Access Transport */ + copy_accTrnspt_to_sngss7(ftdmchan, &iam.accTrnspt); + + SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx IAM clg = \"%s\" (NADI=%d), cld = \"%s\" (NADI=%d)\n", + sngss7_info->circuit->cic, + ftdmchan->caller_data.cid_num.digits, + iam.cgPtyNum.natAddrInd.val, + ftdmchan->caller_data.dnis.digits, + iam.cdPtyNum.natAddrInd.val); } - copy_redirgNum_to_sngss7(ftdmchan, &iam.redirgNum); - - /* check if the user would like us to send a cld_sub-address */ - cld_subAddr = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_cld_subaddr"); - if ((cld_subAddr != NULL) && (*cld_subAddr)) { - SS7_DEBUG_CHAN(ftdmchan,"Found user supplied Called Sub-Address value \"%s\"\n", cld_subAddr); - - /* clean out the subAddrIE */ - memset(subAddrIE, 0x0, sizeof(subAddrIE)); - - /* check the first character in the sub-address to see what type of encoding to use */ - switch (cld_subAddr[0]) { - case '0': /* NSAP */ - encode_subAddrIE_nsap(&cld_subAddr[1], subAddrIE, SNG_CALLED); - break; - case '1': /* national variant */ - encode_subAddrIE_nat(&cld_subAddr[1], subAddrIE, SNG_CALLED); - break; - default: - SS7_ERROR_CHAN(ftdmchan,"Invalid Called Sub-Address encoding requested: %c\n", cld_subAddr[0]); - break; - } /* switch (cld_subAddr[0]) */ - - /* if subaddIE is still empty don't copy it in */ - if (subAddrIE[0] != '0') { - /* check if the cld_subAddr has already been added */ - if (iam.accTrnspt.eh.pres == PRSNT_NODEF) { - /* append the subAddrIE */ - memcpy(&iam.accTrnspt.infoElmts.val[iam.accTrnspt.infoElmts.len], subAddrIE, (subAddrIE[1] + 2)); - iam.accTrnspt.infoElmts.len = iam.accTrnspt.infoElmts.len +subAddrIE[1] + 2; - } else { - /* fill in from the beginning */ - iam.accTrnspt.eh.pres = PRSNT_NODEF; - iam.accTrnspt.infoElmts.pres = PRSNT_NODEF; - memcpy(iam.accTrnspt.infoElmts.val, subAddrIE, (subAddrIE[1] + 2)); - iam.accTrnspt.infoElmts.len = subAddrIE[1] + 2; - } /* if (iam.accTrnspt.eh.pres */ - } /* if (subAddrIE[0] != '0') */ - } /* if ((cld_subAddr != NULL) && (*cld_subAddr)) */ - sng_cc_con_request (sngss7_info->spId, sngss7_info->suInstId, sngss7_info->spInstId, - sngss7_info->circuit->id, - &iam, + sngss7_info->circuit->id, + &iam, 0); - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx IAM clg = \"%s\" (NADI=%d), cld = \"%s\" (NADI=%d)\n", - sngss7_info->circuit->cic, - ftdmchan->caller_data.cid_num.digits, - iam.cgPtyNum.natAddrInd.val, - ftdmchan->caller_data.dnis.digits, - iam.cdPtyNum.natAddrInd.val); - - SS7_FUNC_TRACE_EXIT (__FUNCTION__); return; } @@ -321,7 +168,7 @@ void ft_to_sngss7_acm (ftdm_channel_t * ftdmchan) acm.bckCallInd.echoCtrlDevInd.val = 0x1; break; /**********************************************************************/ - case (FTDM_BEARER_CAP_64K_UNRESTRICTED): + case (FTDM_BEARER_CAP_UNRESTRICTED): acm.bckCallInd.echoCtrlDevInd.val = 0x0; break; /**********************************************************************/ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c index 8fafa8995c..e61153c8e7 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c @@ -33,6 +33,9 @@ /* INCLUDE ********************************************************************/ #include "ftmod_sangoma_ss7_main.h" +#ifdef HAVE_ZLIB +#include +#endif /******************************************************************************/ /* DEFINES ********************************************************************/ @@ -91,9 +94,60 @@ FTDM_ENUM_NAMES(BLK_FLAGS_NAMES, BLK_FLAGS_STRING) FTDM_STR2ENUM(ftmod_ss7_blk_state2flag, ftmod_ss7_blk_flag2str, sng_ckt_block_flag_t, BLK_FLAGS_NAMES, 31) /* FUNCTIONS ******************************************************************/ +static uint8_t get_trillium_val(ftdm2trillium_t *vals, uint8_t ftdm_val, uint8_t default_val); +static uint8_t get_ftdm_val(ftdm2trillium_t *vals, uint8_t trillium_val, uint8_t default_val); + + + +/* Maps generic FreeTDM CPC codes to SS7 CPC codes */ +ftdm2trillium_t cpc_codes[] = { + {FTDM_CPC_UNKNOWN, CAT_UNKNOWN}, + {FTDM_CPC_OPERATOR_FRENCH, CAT_OPLANGFR}, + {FTDM_CPC_OPERATOR_ENGLISH, CAT_OPLANGENG}, + {FTDM_CPC_OPERATOR_GERMAN, CAT_OPLANGGER}, + {FTDM_CPC_OPERATOR_RUSSIAN, CAT_OPLANGRUS}, + {FTDM_CPC_OPERATOR_SPANISH, CAT_OPLANGSP}, + {FTDM_CPC_ORDINARY, CAT_ORD}, + {FTDM_CPC_PRIORITY, CAT_PRIOR}, + {FTDM_CPC_DATA, CAT_DATA}, + {FTDM_CPC_TEST, CAT_TEST}, + {FTDM_CPC_PAYPHONE, CAT_PAYPHONE}, +}; + +ftdm2trillium_t bc_cap_codes[] = { + {FTDM_BEARER_CAP_SPEECH, ITC_SPEECH}, /* speech as per ATIS-1000113.3.2005 */ + {FTDM_BEARER_CAP_UNRESTRICTED, ITC_UNRDIG}, /* unrestricted digital as per ATIS-1000113.3.2005 */ + {FTDM_BEARER_CAP_RESTRICTED, ITC_UNRDIG}, /* Restricted Digital */ + {FTDM_BEARER_CAP_3_1KHZ_AUDIO, ITC_A31KHZ}, /* 3.1kHz audio as per ATIS-1000113.3.2005 */ + {FTDM_BEARER_CAP_7KHZ_AUDIO, ITC_A7KHZ}, /* 7Khz audio */ + {FTDM_BEARER_CAP_15KHZ_AUDIO, ITC_A15KHZ}, /* 15Khz audio */ + {FTDM_BEARER_CAP_VIDEO, ITC_VIDEO}, /* Video */ +}; + +static uint8_t get_trillium_val(ftdm2trillium_t *vals, uint8_t ftdm_val, uint8_t default_val) +{ + ftdm2trillium_t *val = vals; + while(val++) { + if (val->ftdm_val == ftdm_val) { + return val->trillium_val; + } + } + return default_val; +} + +static uint8_t get_ftdm_val(ftdm2trillium_t *vals, uint8_t trillium_val, uint8_t default_val) +{ + ftdm2trillium_t *val = vals; + while(val++) { + if (val->trillium_val == trillium_val) { + return val->ftdm_val; + } + } + return default_val; +} + ftdm_status_t copy_cgPtyNum_from_sngss7(ftdm_channel_t *ftdmchan, SiCgPtyNum *cgPtyNum) { - return FTDM_SUCCESS; } @@ -174,7 +228,6 @@ ftdm_status_t copy_genNmb_to_sngss7(ftdm_channel_t *ftdmchan, SiGenNum *genNmb) { const char *val = NULL; sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; - SS7_FUNC_TRACE_ENTER(__FUNCTION__); val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_gn_digits"); if (!ftdm_strlen_zero(val)) { @@ -183,9 +236,9 @@ ftdm_status_t copy_genNmb_to_sngss7(ftdm_channel_t *ftdmchan, SiGenNum *genNmb) return FTDM_FAIL; } } else { - ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "No user supplied Generic Number qualifier \"%s\"\n", val); return FTDM_SUCCESS; } + genNmb->eh.pres = PRSNT_NODEF; genNmb->addrSig.pres = PRSNT_NODEF; @@ -243,7 +296,6 @@ ftdm_status_t copy_genNmb_to_sngss7(ftdm_channel_t *ftdmchan, SiGenNum *genNmb) genNmb->niInd.val = g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].gn_num_inc_ind; ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "No user supplied Generic Number \"number incomplete indicator\" \"%d\"\n", genNmb->niInd.val); } - SS7_FUNC_TRACE_EXIT(__FUNCTION__); return FTDM_SUCCESS; } @@ -251,7 +303,6 @@ ftdm_status_t copy_genNmb_from_sngss7(ftdm_channel_t *ftdmchan, SiGenNum *genNmb { char val[64]; sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; - SS7_FUNC_TRACE_ENTER(__FUNCTION__); memset(val, 0, sizeof(val)); @@ -301,7 +352,6 @@ ftdm_status_t copy_genNmb_from_sngss7(ftdm_channel_t *ftdmchan, SiGenNum *genNmb sngss7_add_var(sngss7_info, "ss7_gn_num_inc_ind", val); } - SS7_FUNC_TRACE_EXIT(__FUNCTION__); return FTDM_SUCCESS; } @@ -423,6 +473,212 @@ ftdm_status_t copy_redirgNum_from_sngss7(ftdm_channel_t *ftdmchan, SiRedirNum *r return FTDM_SUCCESS; } +ftdm_status_t copy_cgPtyCat_to_sngss7(ftdm_channel_t *ftdmchan, SiCgPtyCat *cgPtyCat) +{ + ftdm_caller_data_t *caller_data = &ftdmchan->caller_data; + + cgPtyCat->eh.pres = PRSNT_NODEF; + cgPtyCat->cgPtyCat.pres = PRSNT_NODEF; + + cgPtyCat->cgPtyCat.val = get_trillium_val(cpc_codes, caller_data->cpc, CAT_ORD); + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Calling Party Category:0x%x\n",cgPtyCat->cgPtyCat.val); + return FTDM_SUCCESS; +} + +ftdm_status_t copy_cgPtyCat_from_sngss7(ftdm_channel_t *ftdmchan, SiCgPtyCat *cgPtyCat) +{ + ftdm_caller_data_t *caller_data = &ftdmchan->caller_data; + + if (cgPtyCat->eh.pres == PRSNT_NODEF && + cgPtyCat->cgPtyCat.pres == PRSNT_NODEF) { + + caller_data->cpc = get_ftdm_val(cpc_codes, cgPtyCat->cgPtyCat.val, FTDM_CPC_UNKNOWN); + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Calling Party Category:0x%x\n", cgPtyCat->cgPtyCat.val); + } + return FTDM_SUCCESS; +} + + +ftdm_status_t copy_accTrnspt_to_sngss7(ftdm_channel_t *ftdmchan, SiAccTrnspt *accTrnspt) +{ + const char *clg_subAddr = NULL; + const char *cld_subAddr = NULL; + char subAddrIE[MAX_SIZEOF_SUBADDR_IE]; + + /* check if the user would like us to send a clg_sub-address */ + clg_subAddr = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_clg_subaddr"); + if (!ftdm_strlen_zero(clg_subAddr)) { + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Calling Sub-Address value \"%s\"\n", clg_subAddr); + + /* clean out the subAddrIE */ + memset(subAddrIE, 0x0, sizeof(subAddrIE)); + + /* check the first character in the sub-address to see what type of encoding to use */ + switch (clg_subAddr[0]) { + case '0': /* NSAP */ + encode_subAddrIE_nsap(&clg_subAddr[1], subAddrIE, SNG_CALLING); + break; + case '1': /* national variant */ + encode_subAddrIE_nat(&clg_subAddr[1], subAddrIE, SNG_CALLING); + break; + default: + ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Invalid Calling Sub-Address encoding requested: %c\n", clg_subAddr[0]); + break; + } /* switch (cld_subAddr[0]) */ + + + /* if subaddIE is still empty don't copy it in */ + if (subAddrIE[0] != '0') { + /* check if the clg_subAddr has already been added */ + if (accTrnspt->eh.pres == PRSNT_NODEF) { + /* append the subAddrIE */ + memcpy(&accTrnspt->infoElmts.val[accTrnspt->infoElmts.len], subAddrIE, (subAddrIE[1] + 2)); + accTrnspt->infoElmts.len = accTrnspt->infoElmts.len +subAddrIE[1] + 2; + } else { + /* fill in from the beginning */ + accTrnspt->eh.pres = PRSNT_NODEF; + accTrnspt->infoElmts.pres = PRSNT_NODEF; + memcpy(accTrnspt->infoElmts.val, subAddrIE, (subAddrIE[1] + 2)); + accTrnspt->infoElmts.len = subAddrIE[1] + 2; + } + } + } + + /* check if the user would like us to send a cld_sub-address */ + cld_subAddr = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_cld_subaddr"); + if ((cld_subAddr != NULL) && (*cld_subAddr)) { + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Called Sub-Address value \"%s\"\n", cld_subAddr); + + /* clean out the subAddrIE */ + memset(subAddrIE, 0x0, sizeof(subAddrIE)); + + /* check the first character in the sub-address to see what type of encoding to use */ + switch (cld_subAddr[0]) { + case '0': /* NSAP */ + encode_subAddrIE_nsap(&cld_subAddr[1], subAddrIE, SNG_CALLED); + break; + case '1': /* national variant */ + encode_subAddrIE_nat(&cld_subAddr[1], subAddrIE, SNG_CALLED); + break; + default: + ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Invalid Called Sub-Address encoding requested: %c\n", cld_subAddr[0]); + break; + } /* switch (cld_subAddr[0]) */ + + /* if subaddIE is still empty don't copy it in */ + if (subAddrIE[0] != '0') { + /* check if the cld_subAddr has already been added */ + if (accTrnspt->eh.pres == PRSNT_NODEF) { + /* append the subAddrIE */ + memcpy(&accTrnspt->infoElmts.val[accTrnspt->infoElmts.len], subAddrIE, (subAddrIE[1] + 2)); + accTrnspt->infoElmts.len = accTrnspt->infoElmts.len +subAddrIE[1] + 2; + } else { + /* fill in from the beginning */ + accTrnspt->eh.pres = PRSNT_NODEF; + accTrnspt->infoElmts.pres = PRSNT_NODEF; + memcpy(accTrnspt->infoElmts.val, subAddrIE, (subAddrIE[1] + 2)); + accTrnspt->infoElmts.len = subAddrIE[1] + 2; + } + } + } /* if ((cld_subAddr != NULL) && (*cld_subAddr)) */ + return FTDM_SUCCESS; +} + +ftdm_status_t copy_natConInd_to_sngss7(ftdm_channel_t *ftdmchan, SiNatConInd *natConInd) +{ + /* copy down the nature of connection indicators */ + natConInd->eh.pres = PRSNT_NODEF; + natConInd->satInd.pres = PRSNT_NODEF; + natConInd->satInd.val = 0; /* no satellite circuit */ + natConInd->contChkInd.pres = PRSNT_NODEF; + natConInd->contChkInd.val = CONTCHK_NOTREQ; + natConInd->echoCntrlDevInd.pres = PRSNT_NODEF; + natConInd->echoCntrlDevInd.val = ECHOCDEV_INCL; + return FTDM_SUCCESS; +} + +ftdm_status_t copy_fwdCallInd_to_sngss7(ftdm_channel_t *ftdmchan, SiFwdCallInd *fwdCallInd) +{ + sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; + + fwdCallInd->eh.pres = PRSNT_NODEF; + fwdCallInd->natIntCallInd.pres = PRSNT_NODEF; + fwdCallInd->natIntCallInd.val = 0x00; + fwdCallInd->end2EndMethInd.pres = PRSNT_NODEF; + fwdCallInd->end2EndMethInd.val = E2EMTH_NOMETH; + fwdCallInd->intInd.pres = PRSNT_NODEF; + fwdCallInd->intInd.val = INTIND_NOINTW; + fwdCallInd->end2EndInfoInd.pres = PRSNT_NODEF; + fwdCallInd->end2EndInfoInd.val = E2EINF_NOINFO; + fwdCallInd->isdnUsrPrtInd.pres = PRSNT_NODEF; + fwdCallInd->isdnUsrPrtInd.val = ISUP_USED; + fwdCallInd->isdnUsrPrtPrfInd.pres = PRSNT_NODEF; + fwdCallInd->isdnUsrPrtPrfInd.val = PREF_PREFAW; + fwdCallInd->isdnAccInd.pres = PRSNT_NODEF; + fwdCallInd->isdnAccInd.val = ISDNACC_ISDN; + fwdCallInd->sccpMethInd.pres = PRSNT_NODEF; + fwdCallInd->sccpMethInd.val = SCCPMTH_NOIND; + + if ((g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].switchType == LSI_SW_ANS88) || + (g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].switchType == LSI_SW_ANS92) || + (g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].switchType == LSI_SW_ANS95)) { + + /* include only if we're running ANSI */ + fwdCallInd->transCallNInd.pres = PRSNT_NODEF; + fwdCallInd->transCallNInd.val = 0x0; + } + return FTDM_SUCCESS; +} + +ftdm_status_t copy_txMedReq_to_sngss7(ftdm_channel_t *ftdmchan, SiTxMedReq *txMedReq) +{ + txMedReq->eh.pres = PRSNT_NODEF; + txMedReq->trMedReq.pres = PRSNT_NODEF; + txMedReq->trMedReq.val = ftdmchan->caller_data.bearer_capability; + + return FTDM_SUCCESS; +} + +ftdm_status_t copy_usrServInfoA_to_sngss7(ftdm_channel_t *ftdmchan, SiUsrServInfo *usrServInfoA) +{ + sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; + + if ((g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].switchType == LSI_SW_ANS88) || + (g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].switchType == LSI_SW_ANS92) || + (g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].switchType == LSI_SW_ANS95)) { + + usrServInfoA->eh.pres = PRSNT_NODEF; + + usrServInfoA->infoTranCap.pres = PRSNT_NODEF; + + usrServInfoA->infoTranCap.val = get_trillium_val(bc_cap_codes, ftdmchan->caller_data.bearer_capability, ITC_SPEECH); + + usrServInfoA->cdeStand.pres = PRSNT_NODEF; + usrServInfoA->cdeStand.val = 0x0; /* ITU-T standardized coding */ + usrServInfoA->tranMode.pres = PRSNT_NODEF; + usrServInfoA->tranMode.val = 0x0; /* circuit mode */ + usrServInfoA->infoTranRate0.pres = PRSNT_NODEF; + usrServInfoA->infoTranRate0.val = 0x10; /* 64kbps origination to destination */ + usrServInfoA->infoTranRate1.pres = PRSNT_NODEF; + usrServInfoA->infoTranRate1.val = 0x10; /* 64kbps destination to origination */ + usrServInfoA->chanStruct.pres = PRSNT_NODEF; + usrServInfoA->chanStruct.val = 0x1; /* 8kHz integrity */ + usrServInfoA->config.pres = PRSNT_NODEF; + usrServInfoA->config.val = 0x0; /* point to point configuration */ + usrServInfoA->establish.pres = PRSNT_NODEF; + usrServInfoA->establish.val = 0x0; /* on demand */ + usrServInfoA->symmetry.pres = PRSNT_NODEF; + usrServInfoA->symmetry.val = 0x0; /* bi-directional symmetric */ + usrServInfoA->usrInfLyr1Prot.pres = PRSNT_NODEF; + usrServInfoA->usrInfLyr1Prot.val = 0x2; /* G.711 ulaw */ + usrServInfoA->rateMultiplier.pres = PRSNT_NODEF; + usrServInfoA->rateMultiplier.val = 0x1; /* 1x rate multipler */ + } /* if ANSI */ + return FTDM_SUCCESS; +} + + + ftdm_status_t copy_tknStr_from_sngss7(TknStr str, char *ftdm, TknU8 oddEven) { uint8_t i; @@ -524,10 +780,17 @@ ftdm_status_t copy_tknStr_to_sngss7(char* val, TknStr *tknStr, TknU8 *oddEven) /* check if the digit is a number and that is not null */ while (!(isxdigit(tmp[0])) && (tmp[0] != '\0')) { - SS7_INFO("Dropping invalid digit: %c\n", tmp[0]); - /* move on to the next value */ - k++; - tmp[0] = val[k]; + if (tmp[0] == '*') { + /* Could not find a spec that specifies this , but on customer system, * was transmitted as 0x0b */ + SS7_DEBUG("Replacing * with 0x0b"); + k++; + tmp[0] = 0x0b; + } else { + SS7_INFO("Dropping invalid digit: %c\n", tmp[0]); + /* move on to the next value */ + k++; + tmp[0] = val[k]; + } } /* while(!(isdigit(tmp))) */ /* check if tmp is null or a digit */ @@ -648,8 +911,6 @@ int check_cics_in_range(sngss7_chan_data_t *sngss7_info) /******************************************************************************/ ftdm_status_t extract_chan_data(uint32_t circuit, sngss7_chan_data_t **sngss7_info, ftdm_channel_t **ftdmchan) { - /*SS7_FUNC_TRACE_ENTER(__FUNCTION__);*/ - if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].obj == NULL) { SS7_ERROR("sngss7_info is Null for circuit #%d\n", circuit); return FTDM_FAIL; @@ -662,7 +923,6 @@ ftdm_status_t extract_chan_data(uint32_t circuit, sngss7_chan_data_t **sngss7_in ftdm_assert_return((*sngss7_info)->ftdmchan, FTDM_FAIL, "received message on signalling link or non-configured cic\n"); *ftdmchan = (*sngss7_info)->ftdmchan; - /*SS7_FUNC_TRACE_EXIT(__FUNCTION__);*/ return FTDM_SUCCESS; } @@ -1291,10 +1551,17 @@ ftdm_status_t encode_subAddrIE_nat(const char *subAddr, char *subAddrIE, int typ /* confirm it is a hex digit */ while ((!isxdigit(tmp[0])) && (tmp[0] != '\0')) { - SS7_INFO("Dropping invalid digit: %c\n", tmp[0]); - /* move to the next character in subAddr */ - x++; - tmp[0] = subAddr[x]; + if (tmp[0] == '*') { + /* Could not find a spec that specifies this, but on customer system, * was transmitted as 0x0b */ + SS7_DEBUG("Replacing * with 0x0b"); + x++; + tmp[0] = 0x0b; + } else { + SS7_INFO("Dropping invalid digit: %c\n", tmp[0]); + /* move to the next character in subAddr */ + x++; + tmp[0] = subAddr[x]; + } } /* check if tmp is null or a digit */ @@ -1651,7 +1918,7 @@ void sngss7_set_sig_status(sngss7_chan_data_t *sngss7_info, ftdm_signaling_statu sig.ev_data.sigstatus.status = status; if (ftdm_span_send_signal(ftdmchan->span, &sig) != FTDM_SUCCESS) { - SS7_ERROR_CHAN(ftdmchan, "Failed to change channel status to %s\n", + ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed to change channel status to %s\n", ftdm_signaling_status2str(status)); } return; @@ -1826,6 +2093,336 @@ ftdm_status_t check_for_reconfig_flag(ftdm_span_t *ftdmspan) return FTDM_SUCCESS; } + +ftdm_status_t sngss7_bufferzero_iam(SiConEvnt *siConEvnt) +{ + if (siConEvnt->natConInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->natConInd, 0, sizeof(siConEvnt->natConInd)); + if (siConEvnt->fwdCallInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->fwdCallInd, 0, sizeof(siConEvnt->fwdCallInd)); + if (siConEvnt->cgPtyCat.eh.pres != PRSNT_NODEF) memset(&siConEvnt->cgPtyCat, 0, sizeof(siConEvnt->cgPtyCat)); + if (siConEvnt->txMedReq.eh.pres != PRSNT_NODEF) memset(&siConEvnt->txMedReq, 0, sizeof(siConEvnt->txMedReq)); +#if (SS7_ANS88 || SS7_ANS92 || SS7_ANS95 || SS7_BELL) + if (siConEvnt->usrServInfoA.eh.pres != PRSNT_NODEF) memset(&siConEvnt->usrServInfoA, 0, sizeof(siConEvnt->usrServInfoA)); +#endif + if (siConEvnt->cdPtyNum.eh.pres != PRSNT_NODEF) memset(&siConEvnt->cdPtyNum, 0, sizeof(siConEvnt->cdPtyNum)); +#if TNS_ANSI +#if (SS7_ANS92 || SS7_ANS95 || SS7_BELL) + if (siConEvnt->tranNetSel1.eh.pres != PRSNT_NODEF) memset(&siConEvnt->tranNetSel1, 0, sizeof(siConEvnt->tranNetSel1)); +#endif +#endif + if (siConEvnt->tranNetSel.eh.pres != PRSNT_NODEF) memset(&siConEvnt->tranNetSel, 0, sizeof(siConEvnt->tranNetSel)); +#if (SS7_ANS88 || SS7_ANS92 || SS7_ANS95 || SS7_BELL || SS7_CHINA) + if (siConEvnt->callRefA.eh.pres != PRSNT_NODEF) memset(&siConEvnt->callRefA, 0, sizeof(siConEvnt->callRefA)); +#endif + if (siConEvnt->callRef.eh.pres != PRSNT_NODEF) memset(&siConEvnt->callRef, 0, sizeof(siConEvnt->callRef)); + if (siConEvnt->cgPtyNum.eh.pres != PRSNT_NODEF) memset(&siConEvnt->cgPtyNum, 0, sizeof(siConEvnt->cgPtyNum)); +#if SS7_BELL + if (siConEvnt->cgPtyNumB.eh.pres != PRSNT_NODEF) memset(&siConEvnt->cgPtyNumB, 0, sizeof(siConEvnt->cgPtyNumB)); +#endif + if (siConEvnt->opFwdCalInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->opFwdCalInd, 0, sizeof(siConEvnt->opFwdCalInd)); +#if (SS7_Q767 || SS7_RUSSIA || SS7_NTT) + if (siConEvnt->opFwdCalIndQ.eh.pres != PRSNT_NODEF) memset(&siConEvnt->opFwdCalIndQ, 0, sizeof(siConEvnt->opFwdCalIndQ)); +#endif +#if SS7_Q767IT + if (siConEvnt->fwdVad.eh.pres != PRSNT_NODEF) memset(&siConEvnt->fwdVad, 0, sizeof(siConEvnt->fwdVad)); +#endif +#if SS7_ANS88 + if (siConEvnt->opFwdCalIndA.eh.pres != PRSNT_NODEF) memset(&siConEvnt->opFwdCalIndA, 0, sizeof(siConEvnt->opFwdCalIndA)); +#endif + if (siConEvnt->redirgNum.eh.pres != PRSNT_NODEF) memset(&siConEvnt->redirgNum, 0, sizeof(siConEvnt->redirgNum)); + if (siConEvnt->redirInfo.eh.pres != PRSNT_NODEF) memset(&siConEvnt->redirInfo, 0, sizeof(siConEvnt->redirInfo)); + if (siConEvnt->cugIntCode.eh.pres != PRSNT_NODEF) memset(&siConEvnt->cugIntCode, 0, sizeof(siConEvnt->cugIntCode)); +#if SS7_ANS88 + if (siConEvnt->cugIntCodeA.eh.pres != PRSNT_NODEF) memset(&siConEvnt->cugIntCodeA, 0, sizeof(siConEvnt->cugIntCodeA)); +#endif +#if (SS7_ANS88 || SS7_ANS92 || SS7_ANS95 || SS7_BELL || SS7_CHINA) + if (siConEvnt->connReqA.eh.pres != PRSNT_NODEF) memset(&siConEvnt->connReqA, 0, sizeof(siConEvnt->connReqA)); +#endif +#if SS7_ANS88 + if (siConEvnt->usr2UsrInfoA.eh.pres != PRSNT_NODEF) memset(&siConEvnt->usr2UsrInfoA, 0, sizeof(siConEvnt->usr2UsrInfoA)); +#endif + if (siConEvnt->connReq.eh.pres != PRSNT_NODEF) memset(&siConEvnt->connReq, 0, sizeof(siConEvnt->connReq)); + if (siConEvnt->origCdNum.eh.pres != PRSNT_NODEF) memset(&siConEvnt->origCdNum, 0, sizeof(siConEvnt->origCdNum)); + if (siConEvnt->usr2UsrInfo.eh.pres != PRSNT_NODEF) memset(&siConEvnt->usr2UsrInfo, 0, sizeof(siConEvnt->usr2UsrInfo)); + if (siConEvnt->accTrnspt.eh.pres != PRSNT_NODEF) memset(&siConEvnt->accTrnspt, 0, sizeof(siConEvnt->accTrnspt)); + if (siConEvnt->echoControl.eh.pres != PRSNT_NODEF) memset(&siConEvnt->echoControl, 0, sizeof(siConEvnt->echoControl)); +#if SS7_ANS88 + if (siConEvnt->redirInfoA.eh.pres != PRSNT_NODEF) memset(&siConEvnt->redirInfoA, 0, sizeof(siConEvnt->redirInfoA)); +#endif +#if (SS7_ANS88 || SS7_ANS92 || SS7_ANS95 || SS7_BELL) + if (siConEvnt->chargeNum.eh.pres != PRSNT_NODEF) memset(&siConEvnt->chargeNum, 0, sizeof(siConEvnt->chargeNum)); + if (siConEvnt->origLineInf.eh.pres != PRSNT_NODEF) memset(&siConEvnt->origLineInf, 0, sizeof(siConEvnt->origLineInf)); +#endif + if (siConEvnt->usrServInfo.eh.pres != PRSNT_NODEF) memset(&siConEvnt->usrServInfo, 0, sizeof(siConEvnt->usrServInfo)); + if (siConEvnt->usr2UsrInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->usr2UsrInd, 0, sizeof(siConEvnt->usr2UsrInd)); + if (siConEvnt->propDly.eh.pres != PRSNT_NODEF) memset(&siConEvnt->propDly, 0, sizeof(siConEvnt->propDly)); + if (siConEvnt->usrServInfo1.eh.pres != PRSNT_NODEF) memset(&siConEvnt->usrServInfo1, 0, sizeof(siConEvnt->usrServInfo1)); + if (siConEvnt->netFac.eh.pres != PRSNT_NODEF) memset(&siConEvnt->netFac, 0, sizeof(siConEvnt->netFac)); +#ifdef SS7_CHINA + if (siConEvnt->orgPteCdeA.eh.pres != PRSNT_NODEF) memset(&siConEvnt->orgPteCdeA, 0, sizeof(siConEvnt->orgPteCdeA)); +#endif + if (siConEvnt->orgPteCde.eh.pres != PRSNT_NODEF) memset(&siConEvnt->orgPteCde, 0, sizeof(siConEvnt->orgPteCde)); + if (siConEvnt->genDigits.eh.pres != PRSNT_NODEF) memset(&siConEvnt->genDigits, 0, sizeof(siConEvnt->genDigits)); + if (siConEvnt->genDigitsR.eh.pres != PRSNT_NODEF) memset(&siConEvnt->genDigitsR, 0, sizeof(siConEvnt->genDigitsR)); + if (siConEvnt->usrTSrvInfo.eh.pres != PRSNT_NODEF) memset(&siConEvnt->usrTSrvInfo, 0, sizeof(siConEvnt->usrTSrvInfo)); + if (siConEvnt->remotOper.eh.pres != PRSNT_NODEF) memset(&siConEvnt->remotOper, 0, sizeof(siConEvnt->remotOper)); + if (siConEvnt->parmCom.eh.pres != PRSNT_NODEF) memset(&siConEvnt->parmCom, 0, sizeof(siConEvnt->parmCom)); +#if (SS7_ANS92 || SS7_ANS95) + if (siConEvnt->servCode.eh.pres != PRSNT_NODEF) memset(&siConEvnt->servCode, 0, sizeof(siConEvnt->servCode)); +#endif +#if SS7_ANS92 + if (siConEvnt->serviceAct1.eh.pres != PRSNT_NODEF) memset(&siConEvnt->serviceAct1, 0, sizeof(siConEvnt->serviceAct1)); +#endif +#if SS7_CHINA + if (siConEvnt->serviceAct2.eh.pres != PRSNT_NODEF) memset(&siConEvnt->serviceAct2, 0, sizeof(siConEvnt->serviceAct2)); +#endif + if (siConEvnt->serviceAct2.eh.pres != PRSNT_NODEF) memset(&siConEvnt->serviceAct2, 0, sizeof(siConEvnt->serviceAct2)); + if (siConEvnt->serviceAct.eh.pres != PRSNT_NODEF) memset(&siConEvnt->serviceAct, 0, sizeof(siConEvnt->serviceAct)); + if (siConEvnt->mlppPrec.eh.pres != PRSNT_NODEF) memset(&siConEvnt->mlppPrec, 0, sizeof(siConEvnt->mlppPrec)); +#if (defined(SIT_PARAMETER) || defined(TDS_ROLL_UPGRADE_SUPPORT)) + if (siConEvnt->txMedUsPr.eh.pres != PRSNT_NODEF) memset(&siConEvnt->txMedUsPr, 0, sizeof(siConEvnt->txMedUsPr)); +#endif + if (siConEvnt->bckCallInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->bckCallInd, 0, sizeof(siConEvnt->bckCallInd)); + if (siConEvnt->cgPtyNum1.eh.pres != PRSNT_NODEF) memset(&siConEvnt->cgPtyNum1, 0, sizeof(siConEvnt->cgPtyNum1)); + if (siConEvnt->optBckCalInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->optBckCalInd, 0, sizeof(siConEvnt->optBckCalInd)); +#if (SS7_Q767 || SS7_RUSSIA || SS7_NTT) + if (siConEvnt->optBckCalIndQ.eh.pres != PRSNT_NODEF) memset(&siConEvnt->optBckCalIndQ, 0, sizeof(siConEvnt->optBckCalIndQ)); +#endif + if (siConEvnt->connNum.eh.pres != PRSNT_NODEF) memset(&siConEvnt->connNum, 0, sizeof(siConEvnt->connNum)); +#if (defined(SIT_PARAMETER) || defined(TDS_ROLL_UPGRADE_SUPPORT)) + if (siConEvnt->connNum2.eh.pres != PRSNT_NODEF) memset(&siConEvnt->connNum2, 0, sizeof(siConEvnt->connNum2)); +#endif + if (siConEvnt->accDelInfo.eh.pres != PRSNT_NODEF) memset(&siConEvnt->accDelInfo, 0, sizeof(siConEvnt->accDelInfo)); + if (siConEvnt->notifInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->notifInd, 0, sizeof(siConEvnt->notifInd)); + if (siConEvnt->notifIndR2.eh.pres != PRSNT_NODEF) memset(&siConEvnt->notifIndR2, 0, sizeof(siConEvnt->notifIndR2)); + if (siConEvnt->cllHstry.eh.pres != PRSNT_NODEF) memset(&siConEvnt->cllHstry, 0, sizeof(siConEvnt->cllHstry)); + if (siConEvnt->genNmb.eh.pres != PRSNT_NODEF) memset(&siConEvnt->genNmb, 0, sizeof(siConEvnt->genNmb)); + if (siConEvnt->genNmbR.eh.pres != PRSNT_NODEF) memset(&siConEvnt->genNmbR, 0, sizeof(siConEvnt->genNmbR)); + if (siConEvnt->redirNum.eh.pres != PRSNT_NODEF) memset(&siConEvnt->redirNum, 0, sizeof(siConEvnt->redirNum)); + if (siConEvnt->redirRstr.eh.pres != PRSNT_NODEF) memset(&siConEvnt->redirRstr, 0, sizeof(siConEvnt->redirRstr)); + +#if SS7_Q767IT + if (siConEvnt->backVad.eh.pres != PRSNT_NODEF) memset(&siConEvnt->backVad, 0, sizeof(siConEvnt->backVad)); +#endif +#if SS7_SINGTEL + if (siConEvnt->cgPtyNumS.eh.pres != PRSNT_NODEF) memset(&siConEvnt->cgPtyNumS, 0, sizeof(siConEvnt->cgPtyNumS)); +#endif +#if (SS7_ANS92 || SS7_ANS95 || SS7_BELL) + if (siConEvnt->businessGrp.eh.pres != PRSNT_NODEF) memset(&siConEvnt->businessGrp, 0, sizeof(siConEvnt->businessGrp)); + if (siConEvnt->infoInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->infoInd, 0, sizeof(siConEvnt->infoInd)); + if (siConEvnt->carrierId.eh.pres != PRSNT_NODEF) memset(&siConEvnt->carrierId, 0, sizeof(siConEvnt->carrierId)); + if (siConEvnt->carSelInf.eh.pres != PRSNT_NODEF) memset(&siConEvnt->carSelInf, 0, sizeof(siConEvnt->carSelInf)); + if (siConEvnt->egress.eh.pres != PRSNT_NODEF) memset(&siConEvnt->egress, 0, sizeof(siConEvnt->egress)); + if (siConEvnt->genAddr.eh.pres != PRSNT_NODEF) memset(&siConEvnt->genAddr, 0, sizeof(siConEvnt->genAddr)); + if (siConEvnt->genAddrR.eh.pres != PRSNT_NODEF) memset(&siConEvnt->genAddrR, 0, sizeof(siConEvnt->genAddrR)); + if (siConEvnt->infoReqInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->infoReqInd, 0, sizeof(siConEvnt->infoReqInd)); + if (siConEvnt->jurisInf.eh.pres != PRSNT_NODEF) memset(&siConEvnt->jurisInf, 0, sizeof(siConEvnt->jurisInf)); + if (siConEvnt->netTransport.eh.pres != PRSNT_NODEF) memset(&siConEvnt->netTransport, 0, sizeof(siConEvnt->netTransport)); + if (siConEvnt->specProcReq.eh.pres != PRSNT_NODEF) memset(&siConEvnt->specProcReq, 0, sizeof(siConEvnt->specProcReq)); + if (siConEvnt->transReq.eh.pres != PRSNT_NODEF) memset(&siConEvnt->transReq, 0, sizeof(siConEvnt->transReq)); +#endif +#if (defined(SIT_PARAMETER) || defined(TDS_ROLL_UPGRADE_SUPPORT)) +#if (SS7_ANS92 || SS7_ANS95) + if (siConEvnt->notifInd1.eh.pres != PRSNT_NODEF) memset(&siConEvnt->notifInd1, 0, sizeof(siConEvnt->notifInd1)); + if (siConEvnt->notifIndR1.eh.pres != PRSNT_NODEF) memset(&siConEvnt->notifIndR1, 0, sizeof(siConEvnt->notifIndR1)); +#endif /* SS7_ANS92 */ +#endif /* SIT_PARAMETER || TDS_ROLL_UPGRADE_SUPPORT */ +#if (SS7_BELL || SS7_ANS95) + if (siConEvnt->genName.eh.pres != PRSNT_NODEF) memset(&siConEvnt->genName, 0, sizeof(siConEvnt->genName)); +#endif +#if (SS7_ITU97 || SS7_RUSS2000 || SS7_ITU2000 || SS7_ETSIV3 || \ + SS7_BELL || SS7_ANS95 || SS7_INDIA || SS7_UK || SS7_NZL || SS7_KZ) + if (siConEvnt->hopCounter.eh.pres != PRSNT_NODEF) memset(&siConEvnt->hopCounter, 0, sizeof(siConEvnt->hopCounter)); +#endif +#if (SS7_BELL || SS7_ITU2000 || SS7_KZ) + if (siConEvnt->redirCap.eh.pres != PRSNT_NODEF) memset(&siConEvnt->redirCap, 0, sizeof(siConEvnt->redirCap)); + if (siConEvnt->redirCntr.eh.pres != PRSNT_NODEF) memset(&siConEvnt->redirCntr, 0, sizeof(siConEvnt->redirCntr)); +#endif +#if (SS7_ETSI || SS7_FTZ) + if (siConEvnt->ccbsParam.eh.pres != PRSNT_NODEF) memset(&siConEvnt->ccbsParam, 0, sizeof(siConEvnt->ccbsParam)); + if (siConEvnt->freePhParam.eh.pres != PRSNT_NODEF) memset(&siConEvnt->freePhParam, 0, sizeof(siConEvnt->freePhParam)); +#endif +#ifdef SS7_FTZ + if (siConEvnt->naPaFF.eh.pres != PRSNT_NODEF) memset(&siConEvnt->naPaFF, 0, sizeof(siConEvnt->naPaFF)); + if (siConEvnt->naPaFE.eh.pres != PRSNT_NODEF) memset(&siConEvnt->naPaFE, 0, sizeof(siConEvnt->naPaFE)); + if (siConEvnt->naPaSSP.eh.pres != PRSNT_NODEF) memset(&siConEvnt->naPaSSP, 0, sizeof(siConEvnt->naPaSSP)); + if (siConEvnt->naPaCdPNO.eh.pres != PRSNT_NODEF) memset(&siConEvnt->naPaCdPNO, 0, sizeof(siConEvnt->naPaCdPNO)); + if (siConEvnt->naPaSPV.eh.pres != PRSNT_NODEF) memset(&siConEvnt->naPaSPV, 0, sizeof(siConEvnt->naPaSPV)); + if (siConEvnt->naPaUKK.eh.pres != PRSNT_NODEF) memset(&siConEvnt->naPaUKK, 0, sizeof(siConEvnt->naPaUKK)); +#endif +#if SS7_NTT + if (siConEvnt->msgAreaInfo.eh.pres != PRSNT_NODEF) memset(&siConEvnt->msgAreaInfo, 0, sizeof(siConEvnt->msgAreaInfo)); + if (siConEvnt->subsNumber.eh.pres != PRSNT_NODEF) memset(&siConEvnt->subsNumber, 0, sizeof(siConEvnt->subsNumber)); + if (siConEvnt->rpCllngNo.eh.pres != PRSNT_NODEF) memset(&siConEvnt->rpCllngNo, 0, sizeof(siConEvnt->rpCllngNo)); + if (siConEvnt->supplUserType.eh.pres != PRSNT_NODEF) memset(&siConEvnt->supplUserType, 0, sizeof(siConEvnt->supplUserType)); + if (siConEvnt->carrierInfoTrans.eh.pres != PRSNT_NODEF) memset(&siConEvnt->carrierInfoTrans, 0, sizeof(siConEvnt->carrierInfoTrans)); + if (siConEvnt->nwFuncType.eh.pres != PRSNT_NODEF) memset(&siConEvnt->nwFuncType, 0, sizeof(siConEvnt->nwFuncType)); +#endif +#if SS7_ANS95 + if (siConEvnt->optrServicesInfo.eh.pres != PRSNT_NODEF) memset(&siConEvnt->optrServicesInfo, 0, sizeof(siConEvnt->optrServicesInfo)); +#endif +#if (SS7_ANS95 || SS7_ITU97 || SS7_RUSS2000|| SS7_ITU2000 || SS7_NZL || SS7_KZ) + if (siConEvnt->cirAsgnMap.eh.pres != PRSNT_NODEF) memset(&siConEvnt->cirAsgnMap, 0, sizeof(siConEvnt->cirAsgnMap)); +#endif +#if (SS7_ITU97 || SS7_RUSS2000 || SS7_ITU2000 || SS7_ETSIV3 || \ + SS7_INDIA || SS7_UK || SS7_NZL || SS7_KZ) + if (siConEvnt->displayInfo.eh.pres != PRSNT_NODEF) memset(&siConEvnt->displayInfo, 0, sizeof(siConEvnt->displayInfo)); + if (siConEvnt->confTrtInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->confTrtInd, 0, sizeof(siConEvnt->confTrtInd)); + if (siConEvnt->netMgmtControls.eh.pres != PRSNT_NODEF) memset(&siConEvnt->netMgmtControls, 0, sizeof(siConEvnt->netMgmtControls)); + if (siConEvnt->correlationId.eh.pres != PRSNT_NODEF) memset(&siConEvnt->correlationId, 0, sizeof(siConEvnt->correlationId)); + if (siConEvnt->callDivTrtInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->callDivTrtInd, 0, sizeof(siConEvnt->callDivTrtInd)); + if (siConEvnt->callInNmb.eh.pres != PRSNT_NODEF) memset(&siConEvnt->callInNmb, 0, sizeof(siConEvnt->callInNmb)); + if (siConEvnt->callOfferTrtInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->callOfferTrtInd, 0, sizeof(siConEvnt->callOfferTrtInd)); + if (siConEvnt->scfId.eh.pres != PRSNT_NODEF) memset(&siConEvnt->scfId, 0, sizeof(siConEvnt->scfId)); + if (siConEvnt->uidCapInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->uidCapInd, 0, sizeof(siConEvnt->uidCapInd)); + if (siConEvnt->collCallReq.eh.pres != PRSNT_NODEF) memset(&siConEvnt->collCallReq, 0, sizeof(siConEvnt->collCallReq)); + if (siConEvnt->ccss.eh.pres != PRSNT_NODEF) memset(&siConEvnt->ccss, 0, sizeof(siConEvnt->ccss)); +#endif +#if (SS7_ITU97 || SS7_RUSS2000 || SS7_ITU2000 || SS7_UK || SS7_NZL || SS7_KZ) + if (siConEvnt->backGVNS.eh.pres != PRSNT_NODEF) memset(&siConEvnt->backGVNS, 0, sizeof(siConEvnt->backGVNS)); + if (siConEvnt->forwardGVNS.eh.pres != PRSNT_NODEF) memset(&siConEvnt->forwardGVNS, 0, sizeof(siConEvnt->forwardGVNS)); +#endif +#if (SS7_ETSIV3 || SS7_ITU97 || SS7_RUSS2000 || SS7_ITU2000 || \ + SS7_INDIA || SS7_UK || SS7_NZL || SS7_KZ) + if (siConEvnt->appTransParam.eh.pres != PRSNT_NODEF) memset(&siConEvnt->appTransParam, 0, sizeof(siConEvnt->appTransParam)); +#endif +#if (SS7_ITU2000 || SS7_UK || SS7_NZL || SS7_KZ) + if (siConEvnt->htrInfo.eh.pres != PRSNT_NODEF) memset(&siConEvnt->htrInfo, 0, sizeof(siConEvnt->htrInfo)); + if (siConEvnt->pivotCap.eh.pres != PRSNT_NODEF) memset(&siConEvnt->pivotCap, 0, sizeof(siConEvnt->pivotCap)); + if (siConEvnt->cadDirNmb.eh.pres != PRSNT_NODEF) memset(&siConEvnt->cadDirNmb, 0, sizeof(siConEvnt->cadDirNmb)); + if (siConEvnt->origCallInNum.eh.pres != PRSNT_NODEF) memset(&siConEvnt->origCallInNum, 0, sizeof(siConEvnt->origCallInNum)); + if (siConEvnt->calgGeoLoc.eh.pres != PRSNT_NODEF) memset(&siConEvnt->calgGeoLoc, 0, sizeof(siConEvnt->calgGeoLoc)); + if (siConEvnt->netRoutNum.eh.pres != PRSNT_NODEF) memset(&siConEvnt->netRoutNum, 0, sizeof(siConEvnt->netRoutNum)); + if (siConEvnt->qonRelCap.eh.pres != PRSNT_NODEF) memset(&siConEvnt->qonRelCap, 0, sizeof(siConEvnt->qonRelCap)); + if (siConEvnt->pivotCntr.eh.pres != PRSNT_NODEF) memset(&siConEvnt->pivotCntr, 0, sizeof(siConEvnt->pivotCntr)); + if (siConEvnt->pivotRtgFwInfo.eh.pres != PRSNT_NODEF) memset(&siConEvnt->pivotRtgFwInfo, 0, sizeof(siConEvnt->pivotRtgFwInfo)); + if (siConEvnt->pivotRtgBkInfo.eh.pres != PRSNT_NODEF) memset(&siConEvnt->pivotRtgBkInfo, 0, sizeof(siConEvnt->pivotRtgBkInfo)); + if (siConEvnt->numPortFwdInfo.eh.pres != PRSNT_NODEF) memset(&siConEvnt->numPortFwdInfo, 0, sizeof(siConEvnt->numPortFwdInfo)); +#endif +#ifdef SS7_UK + if (siConEvnt->natFwdCalInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->natFwdCalInd, 0, sizeof(siConEvnt->natFwdCalInd)); + if (siConEvnt->presntNum.eh.pres != PRSNT_NODEF) memset(&siConEvnt->presntNum, 0, sizeof(siConEvnt->presntNum)); + if (siConEvnt->lstDvrtLineId.eh.pres != PRSNT_NODEF) memset(&siConEvnt->lstDvrtLineId, 0, sizeof(siConEvnt->lstDvrtLineId)); + if (siConEvnt->pcgLineId.eh.pres != PRSNT_NODEF) memset(&siConEvnt->pcgLineId, 0, sizeof(siConEvnt->pcgLineId)); + if (siConEvnt->natFwdCalIndLnk.eh.pres != PRSNT_NODEF) memset(&siConEvnt->natFwdCalIndLnk, 0, sizeof(siConEvnt->natFwdCalIndLnk)); + if (siConEvnt->cdBascSrvcMrk.eh.pres != PRSNT_NODEF) memset(&siConEvnt->cdBascSrvcMrk, 0, sizeof(siConEvnt->cdBascSrvcMrk)); +#endif /* SS7_UK */ +#if (defined(CGPN_CHK)) + if (siConEvnt->causeDgnCgPnChk.eh.pres != PRSNT_NODEF) memset(&siConEvnt->causeDgnCgPnChk, 0, sizeof(siConEvnt->causeDgnCgPnChk)); +#endif + return FTDM_SUCCESS; +} + +ftdm_status_t sngss7_save_iam(ftdm_channel_t *ftdmchan, SiConEvnt *siConEvnt) +{ +#ifndef HAVE_ZLIB + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Cannot perform transparent IAM because zlib is missing\n"); + return FTDM_FAIL; +#else + unsigned ret_val = FTDM_FAIL; + char *compressed_iam = NULL; + char *url_encoded_iam = NULL; + uLongf len = sizeof(*siConEvnt); + sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; + + /* By default, Trillium does not memset their whole structure to zero for + * performance. But we want to memset all the IE's that are not present to + * optimize compressed size */ + sngss7_bufferzero_iam(siConEvnt); + + compressed_iam = ftdm_malloc(sizeof(*siConEvnt)); + if (!compressed_iam) { + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to allocate buffer for compressed_iam\n"); + goto done; + } + + /* Compress IAM structure to minimize buffer size */ + ret_val = compress((Bytef *)compressed_iam, &len, (const Bytef *)siConEvnt, (uLong)sizeof(*siConEvnt)); + if (ret_val != Z_OK) { + ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Failed to compress IAM (error:%d)\n", ret_val); + ret_val = FTDM_FAIL; + goto done; + } + + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Compressed IAM size:%d\n", len); + + /* Worst case: size will triple after url encode */ + url_encoded_iam = ftdm_malloc(3*sizeof(*siConEvnt)); + if (!url_encoded_iam) { + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to allocated buffer for url_encoded_iam\n"); + ret_val = FTDM_FAIL; + goto done; + } + memset(url_encoded_iam, 0, 2*sizeof(*siConEvnt)); + + /* URL encode buffer to that its safe to store it in a string */ + ftdm_url_encode((const char*)compressed_iam, url_encoded_iam, len); + + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "IAM variable length:%d\n", strlen(url_encoded_iam)); + + if (strlen(url_encoded_iam) > g_ftdm_sngss7_data.cfg.transparent_iam_max_size) { + ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "IAM variable length exceeds max size (len:%d max:%d) \n", strlen(url_encoded_iam), g_ftdm_sngss7_data.cfg.transparent_iam_max_size); + ret_val = FTDM_FAIL; + goto done; + } + + sngss7_add_var(sngss7_info, "ss7_iam", url_encoded_iam); +done: + ftdm_safe_free(compressed_iam); + ftdm_safe_free(url_encoded_iam); + return ret_val; +#endif +} + +ftdm_status_t sngss7_retrieve_iam(ftdm_channel_t *ftdmchan, SiConEvnt *siConEvnt) +{ +#ifndef HAVE_ZLIB + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Cannot perform transparent IAM because zlib is missing\n"); + return FTDM_FAIL; +#else + uLongf len = 3*sizeof(*siConEvnt); /* worst case: URL encoded buffer is 3x length of buffer */ + char *val = NULL; + unsigned ret_val = FTDM_FAIL; + void *uncompressed_buffer = NULL; + char *url_encoded_iam = NULL; + ftdm_size_t url_encoded_iam_len; + + val = (char*)ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_iam"); + if (ftdm_strlen_zero(val)) { + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "No Transparent IAM info available\n"); + return FTDM_FAIL; + } + + url_encoded_iam = ftdm_strdup(val); + + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "IAM variable length:%d\n", strlen(val)); + ftdm_url_decode(url_encoded_iam, &url_encoded_iam_len); + + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Compressed IAM size:%d\n", url_encoded_iam_len); + + uncompressed_buffer = ftdm_malloc(sizeof(*siConEvnt)); + ftdm_assert_return(uncompressed_buffer, FTDM_FAIL, "Failed to allocate buffer for uncompressed buffer\n"); + + ret_val = uncompress(uncompressed_buffer, &len, (const Bytef *)url_encoded_iam, (uLong)url_encoded_iam_len); + if (ret_val != Z_OK) { + ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Failed to uncompress IAM (error:%d)\n", ret_val); + goto done; + } + + if (len != sizeof(*siConEvnt)) { + ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Incompatible IAM structure size (expected:%d size:%d)\n", sizeof(*siConEvnt), strlen(uncompressed_buffer)); + goto done; + } + + memcpy(siConEvnt, uncompressed_buffer, sizeof(*siConEvnt)); + ret_val = FTDM_SUCCESS; + +done: + ftdm_safe_free(uncompressed_buffer); + ftdm_safe_free(url_encoded_iam); + return ret_val; +#endif +} + /******************************************************************************/ /* For Emacs: * Local Variables: diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c index 2df0a88edb..a891c50108 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c @@ -124,7 +124,8 @@ typedef struct sng_ccSpan uint32_t cld_nadi; uint32_t rdnis_nadi; uint32_t min_digits; - uint32_t itx_auto_reply; + uint8_t itx_auto_reply; + uint8_t transparent_iam; uint32_t t3; uint32_t t12; uint32_t t13; @@ -466,6 +467,9 @@ static int ftmod_ss7_parse_sng_gen(ftdm_conf_node_t *sng_gen) SS7_DEBUG("Found license file = %s\n", g_ftdm_sngss7_data.cfg.license); SS7_DEBUG("Found signature file = %s\n", g_ftdm_sngss7_data.cfg.signature); /**********************************************************************/ + } else if (!strcasecmp(parm->var, "transparent_iam_max_size")) { + g_ftdm_sngss7_data.cfg.transparent_iam_max_size = atoi(parm->val); + SS7_DEBUG("Found a transparent_iam max size = %d\n", g_ftdm_sngss7_data.cfg.transparent_iam_max_size); } else { /**********************************************************************/ SS7_ERROR("Found an invalid parameter \"%s\"!\n", parm->val); @@ -1896,6 +1900,13 @@ static int ftmod_ss7_parse_cc_span(ftdm_conf_node_t *cc_span) } else if (!strcasecmp(parm->var, "itx_auto_reply")) { sng_ccSpan.itx_auto_reply = ftdm_true(parm->val); SS7_DEBUG("Found itx_auto_reply %d\n", sng_ccSpan.itx_auto_reply); + } else if (!strcasecmp(parm->var, "transparent_iam")) { +#ifndef HAVE_ZLIB + SS7_CRIT("Cannot enable transparent IAM becauze zlib not installed\n"); +#else + sng_ccSpan.transparent_iam = ftdm_true(parm->val); + SS7_DEBUG("Found transparent_iam %d\n", sng_ccSpan.transparent_iam); +#endif } else if (!strcasecmp(parm->var, "cicbase")) { /**********************************************************************/ sng_ccSpan.cicbase = atoi(parm->val); @@ -2907,16 +2918,17 @@ static int ftmod_ss7_fill_in_ccSpan(sng_ccSpan_t *ccSpan) g_ftdm_sngss7_data.cfg.isupCkt[x].cic = 0; } - g_ftdm_sngss7_data.cfg.isupCkt[x].infId = ccSpan->isupInf; - g_ftdm_sngss7_data.cfg.isupCkt[x].typeCntrl = ccSpan->typeCntrl; - g_ftdm_sngss7_data.cfg.isupCkt[x].ssf = ccSpan->ssf; - g_ftdm_sngss7_data.cfg.isupCkt[x].cld_nadi = ccSpan->cld_nadi; - g_ftdm_sngss7_data.cfg.isupCkt[x].clg_nadi = ccSpan->clg_nadi; - g_ftdm_sngss7_data.cfg.isupCkt[x].rdnis_nadi = ccSpan->rdnis_nadi; - g_ftdm_sngss7_data.cfg.isupCkt[x].options = ccSpan->options; - g_ftdm_sngss7_data.cfg.isupCkt[x].switchType = ccSpan->switchType; - g_ftdm_sngss7_data.cfg.isupCkt[x].min_digits = ccSpan->min_digits; - g_ftdm_sngss7_data.cfg.isupCkt[x].itx_auto_reply = ccSpan->itx_auto_reply; + g_ftdm_sngss7_data.cfg.isupCkt[x].infId = ccSpan->isupInf; + g_ftdm_sngss7_data.cfg.isupCkt[x].typeCntrl = ccSpan->typeCntrl; + g_ftdm_sngss7_data.cfg.isupCkt[x].ssf = ccSpan->ssf; + g_ftdm_sngss7_data.cfg.isupCkt[x].cld_nadi = ccSpan->cld_nadi; + g_ftdm_sngss7_data.cfg.isupCkt[x].clg_nadi = ccSpan->clg_nadi; + g_ftdm_sngss7_data.cfg.isupCkt[x].rdnis_nadi = ccSpan->rdnis_nadi; + g_ftdm_sngss7_data.cfg.isupCkt[x].options = ccSpan->options; + g_ftdm_sngss7_data.cfg.isupCkt[x].switchType = ccSpan->switchType; + g_ftdm_sngss7_data.cfg.isupCkt[x].min_digits = ccSpan->min_digits; + g_ftdm_sngss7_data.cfg.isupCkt[x].itx_auto_reply = ccSpan->itx_auto_reply; + g_ftdm_sngss7_data.cfg.isupCkt[x].transparent_iam = ccSpan->transparent_iam; if (ccSpan->t3 == 0) { g_ftdm_sngss7_data.cfg.isupCkt[x].t3 = 1200; diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c index 3a2e72e69b..2bf9f6bc2e 100644 --- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c +++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c @@ -950,7 +950,6 @@ static void wanpipe_read_stats(ftdm_channel_t *ftdmchan, wp_tdm_api_rx_hdr_t *rx static FIO_READ_FUNCTION(wanpipe_read) { int rx_len = 0; - int myerrno = 0; wp_tdm_api_rx_hdr_t hdrframe; memset(&hdrframe, 0, sizeof(hdrframe)); @@ -964,7 +963,6 @@ static FIO_READ_FUNCTION(wanpipe_read) } if (rx_len < 0) { - myerrno = errno; snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", strerror(errno)); ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Failed to read from sangoma device: %s (%d)\n", strerror(errno), rx_len); return FTDM_FAIL; diff --git a/libs/freetdm/src/include/freetdm.h b/libs/freetdm/src/include/freetdm.h index 6ab518a6e3..253f256ffa 100755 --- a/libs/freetdm/src/include/freetdm.h +++ b/libs/freetdm/src/include/freetdm.h @@ -241,12 +241,12 @@ FTDM_STR2ENUM_P(ftdm_str2ftdm_ton, ftdm_ton2str, ftdm_ton_t) /*! Numbering Plan Identification (NPI) */ typedef enum { FTDM_NPI_UNKNOWN = 0, - FTDM_NPI_ISDN = 1, - FTDM_NPI_DATA = 3, - FTDM_NPI_TELEX = 4, - FTDM_NPI_NATIONAL = 8, - FTDM_NPI_PRIVATE = 9, - FTDM_NPI_RESERVED = 10, + FTDM_NPI_ISDN, + FTDM_NPI_DATA, + FTDM_NPI_TELEX, + FTDM_NPI_NATIONAL, + FTDM_NPI_PRIVATE, + FTDM_NPI_RESERVED, FTDM_NPI_INVALID } ftdm_npi_t; #define NPI_STRINGS "unknown", "ISDN", "data", "telex", "national", "private", "reserved", "invalid" @@ -276,12 +276,16 @@ FTDM_STR2ENUM_P(ftdm_str2ftdm_screening, ftdm_screening2str, ftdm_screening_t) /*! \brief bearer capability */ typedef enum { - FTDM_BEARER_CAP_SPEECH = 0x00, - FTDM_BEARER_CAP_64K_UNRESTRICTED = 0x02, - FTDM_BEARER_CAP_3_1KHZ_AUDIO = 0x03, + FTDM_BEARER_CAP_SPEECH = 0x00, /* Speech */ + FTDM_BEARER_CAP_UNRESTRICTED, /* Unrestricted Digital */ + FTDM_BEARER_CAP_RESTRICTED, /* Restricted Digital */ + FTDM_BEARER_CAP_3_1KHZ_AUDIO, /* 3.1 Khz Audio */ + FTDM_BEARER_CAP_7KHZ_AUDIO, /* 7 Khz Audio or Unrestricted digital w tones */ + FTDM_BEARER_CAP_15KHZ_AUDIO, /* 15 Khz Audio */ + FTDM_BEARER_CAP_VIDEO, /* Video */ FTDM_BEARER_CAP_INVALID } ftdm_bearer_cap_t; -#define BEARER_CAP_STRINGS "speech", "unrestricted-digital-information", "3.1-Khz-audio", "invalid" +#define BEARER_CAP_STRINGS "speech", "unrestricted-digital-information", "restricted-digital-information", "3.1-Khz-audio", "7-Khz-audio", "15-Khz-audio", "video", "invalid" FTDM_STR2ENUM_P(ftdm_str2ftdm_bearer_cap, ftdm_bearer_cap2str, ftdm_bearer_cap_t) /*! \brief user information layer 1 protocol */ @@ -298,6 +302,11 @@ FTDM_STR2ENUM_P(ftdm_str2ftdm_usr_layer1_prot, ftdm_user_layer1_prot2str, ftdm_u typedef enum { FTDM_CPC_UNKNOWN, FTDM_CPC_OPERATOR, + FTDM_CPC_OPERATOR_FRENCH, + FTDM_CPC_OPERATOR_ENGLISH, + FTDM_CPC_OPERATOR_GERMAN, + FTDM_CPC_OPERATOR_RUSSIAN, + FTDM_CPC_OPERATOR_SPANISH, FTDM_CPC_ORDINARY, FTDM_CPC_PRIORITY, FTDM_CPC_DATA, @@ -305,12 +314,14 @@ typedef enum { FTDM_CPC_PAYPHONE, FTDM_CPC_INVALID } ftdm_calling_party_category_t; -#define CALLING_PARTY_CATEGORY_STRINGS "unknown", "operator", "ordinary", "priority", "data-call", "test-call", "payphone", "invalid" +#define CALLING_PARTY_CATEGORY_STRINGS "unknown", "operator", "operator-french", "operator-english", "operator-german", "operator-russian", "operator-spanish", "ordinary", "priority", "data-call", "test-call", "payphone", "invalid" FTDM_STR2ENUM_P(ftdm_str2ftdm_calling_party_category, ftdm_calling_party_category2str, ftdm_calling_party_category_t) /*! \brief Digit limit used in DNIS/ANI */ #define FTDM_DIGITS_LIMIT 25 +#define FTDM_SILENCE_VALUE(fchan) (fchan)->native_codec == FTDM_CODEC_ULAW ? 255 : (fchan)->native_codec == FTDM_CODEC_ALAW ? 0xD5 : 0x00 + /*! \brief Number abstraction */ typedef struct { char digits[FTDM_DIGITS_LIMIT]; diff --git a/libs/freetdm/src/include/ftdm_call_utils.h b/libs/freetdm/src/include/ftdm_call_utils.h index 2418273343..975e73e729 100644 --- a/libs/freetdm/src/include/ftdm_call_utils.h +++ b/libs/freetdm/src/include/ftdm_call_utils.h @@ -131,5 +131,24 @@ FT_DECLARE(ftdm_status_t) ftdm_is_number(const char *number); */ FT_DECLARE(ftdm_status_t) ftdm_set_calling_party_category(const char *string, uint8_t *target); +/*! + * \brief URL encode a buffer + * + * \param url buffer to convert + * \param buf target to save converted string to + * \param len size of buffer + * + * \retval pointer to converted string + */ +FT_DECLARE(char *) ftdm_url_encode(const char *url, char *buf, ftdm_size_t len); + +/*! + * \param s buffer to convert + * \param len size of buffer + * + * \retval pointer to converted string + */ +FT_DECLARE(char *) ftdm_url_decode(char *s, ftdm_size_t *len); + #endif /* __FTDM_CALL_UTILS_H__ */ diff --git a/libs/freetdm/src/include/private/ftdm_types.h b/libs/freetdm/src/include/private/ftdm_types.h index b263b64a2d..e4d2b6900d 100755 --- a/libs/freetdm/src/include/private/ftdm_types.h +++ b/libs/freetdm/src/include/private/ftdm_types.h @@ -249,6 +249,8 @@ typedef enum { #define FTDM_CHANNEL_IND_ACK_PENDING (1ULL << 34) /*!< There is someone blocking in the channel waiting for state completion */ #define FTDM_CHANNEL_BLOCKING (1ULL << 35) +/*!< Media is digital */ +#define FTDM_CHANNEL_DIGITAL_MEDIA (1ULL << 36) #include "ftdm_state.h" diff --git a/libs/freetdm/src/libteletone_generate.c b/libs/freetdm/src/libteletone_generate.c index 7f37b7a258..c0d6a54349 100644 --- a/libs/freetdm/src/libteletone_generate.c +++ b/libs/freetdm/src/libteletone_generate.c @@ -273,7 +273,7 @@ TELETONE_API(int) teletone_mux_tones(teletone_generation_session_t *ts, teletone TELETONE_API(int) teletone_run(teletone_generation_session_t *ts, const char *cmd) { char *data = NULL, *cur = NULL, *end = NULL; - int var = 0, LOOPING = 0; + int LOOPING = 0; if (!cmd) { return -1; @@ -287,7 +287,6 @@ TELETONE_API(int) teletone_run(teletone_generation_session_t *ts, const char *cm cur = data; while (*cur) { - var = 0; if (*cur == ' ' || *cur == '\r' || *cur == '\n') { cur++; continue; @@ -298,7 +297,6 @@ TELETONE_API(int) teletone_run(teletone_generation_session_t *ts, const char *cm } if (*(cur + 1) == '=') { - var = 1; switch(*cur) { case 'c': ts->channels = atoi(cur + 2); diff --git a/libs/libdingaling/src/libdingaling.c b/libs/libdingaling/src/libdingaling.c index 6793c3df61..bbf26ca5c9 100644 --- a/libs/libdingaling/src/libdingaling.c +++ b/libs/libdingaling/src/libdingaling.c @@ -242,7 +242,7 @@ static void default_logger(char *file, const char *func, int line, int level, ch vsnprintf(data, sizeof(data), fmt, ap); - fprintf(globals.log_stream, "%s:%d %s() %s", file, line, func, data); + fprintf(globals.log_stream, "%s:%d %s() %s", fp, line, func, data); va_end(ap); @@ -997,9 +997,9 @@ static int on_commands(void *user_data, ikspak *pak) uint8_t is_result = strcasecmp(type, "result") ? 0 : 1; uint8_t is_error = strcasecmp(type, "error") ? 0 : 1; iks *xml, *xsession, *xerror = NULL, *xredir = NULL; - struct iks_tag* tmp; + xml = iks_child (pak->x); - tmp = (struct iks_tag*) xml; + if (is_error) { if ((xerror = working_find(xml, "error"))) { char *code = iks_find_attrib(xerror, "code"); diff --git a/scripts/lua/sound_test.lua b/scripts/lua/sound_test.lua new file mode 100644 index 0000000000..e29c2f9ca7 --- /dev/null +++ b/scripts/lua/sound_test.lua @@ -0,0 +1,74 @@ +-- +-- sound_test.lua +-- +-- accepts two args and then rolls through the sound files +-- arg 1: type +-- arg 2: rate +-- +--[[ Use a dialplan entry like this: + + + + + + + + +Note the syntax of the destination number: +Rate can be 8000, 16000, 32000, or 48000 +Type can be ivr, conference, voicemail, misc, digits, etc. + +Using the extension listed above you could call it with mod_portaudio from fs_cli: + + pa call 16000ivr + pa call 8000conference + pa call 32000conference + + etc. + +]] + +-- Create tables that hold our rates and types + +tbl_types = { + ['ascii'] = 1, + ['base256'] = 1, + ['conference'] = 1, + ['currency'] = 1, + ['digits'] = 1, + ['directory'] = 1, + ['ivr'] = 1, + ['misc'] = 1, + ['phonetic-ascii'] = 1, + ['time'] = 1, + ['voicemail'] = 1, + ['zrtp'] = 1 +}; + +tbl_rates = {['8000'] = 1 ,['16000'] = 1, ['32000'] = 1, ['48000'] = 1}; + +stype = argv[1]; +srate = argv[2]; + +freeswitch.consoleLog("INFO","Args: Type = " .. argv[1] .. ', Rate = ' .. argv[2] .. "\n"); + +if ( tbl_types[stype] == nil ) then + freeswitch.consoleLog("ERR","Type '" .. stype .. "' is not valid.\n"); +elseif ( tbl_rates[srate] == nil ) then + freeswitch.consoleLog("ERR","Rate '" .. srate .. "' is not valid.\n"); +else + -- Looks good, let's play some sound files + sound_base = session:getVariable('sounds_dir') .. '/en/us/callie/' .. stype .. '/' .. srate; + input_file = '/tmp/filez.txt'; + res = os.execute('ls -1 ' .. sound_base .. ' > ' .. input_file); + freeswitch.consoleLog("INFO","Result of system call: " .. res .. "\n"); + if ( res == 0 ) then + for fname in io.lines(input_file) do + freeswitch.consoleLog("NOTICE","Playing file: " .. fname .. "\n"); + session:streamFile(sound_base .. '/' .. fname); + session:sleep(100); + end + else + freeswitch.consoleLog("ERR","Result of system call: " .. res .. "\n"); + end +end \ No newline at end of file diff --git a/src/include/private/switch_core_pvt.h b/src/include/private/switch_core_pvt.h index 8102d038e3..8c1ac3707c 100644 --- a/src/include/private/switch_core_pvt.h +++ b/src/include/private/switch_core_pvt.h @@ -253,6 +253,8 @@ struct switch_runtime { int multiple_registrations; uint32_t max_db_handles; uint32_t db_handle_timeout; + int curl_count; + int ssl_count; }; extern struct switch_runtime runtime; diff --git a/src/include/switch_caller.h b/src/include/switch_caller.h index bd53a04f68..fde3372105 100644 --- a/src/include/switch_caller.h +++ b/src/include/switch_caller.h @@ -56,6 +56,15 @@ #include SWITCH_BEGIN_EXTERN_C + +typedef struct profile_node_s { + char *var; + char *val; + struct profile_node_s *next; +} profile_node_t; + + + /*! \brief Call Specific Data */ struct switch_caller_profile { @@ -110,6 +119,7 @@ SWITCH_BEGIN_EXTERN_C switch_memory_pool_t *pool; struct switch_caller_profile *next; switch_call_direction_t direction; + profile_node_t *soft; }; /*! \brief An Abstract Representation of a dialplan Application */ diff --git a/src/include/switch_core.h b/src/include/switch_core.h index 88e8152f2a..ee890a80c9 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -57,6 +57,7 @@ SWITCH_BEGIN_EXTERN_C struct switch_app_log { char *app; char *arg; + switch_time_t stamp; struct switch_app_log *next; }; @@ -434,6 +435,9 @@ SWITCH_DECLARE(void) switch_core_session_rwunlock(_In_ switch_core_session_t *se */ SWITCH_DECLARE(int) switch_core_add_state_handler(_In_ const switch_state_handler_table_t *state_handler); +SWITCH_DECLARE(int) switch_core_curl_count(int *val); +SWITCH_DECLARE(int) switch_core_ssl_count(int *val); + /*! \brief Remove a global state handler \param state_handler the state handler to remove diff --git a/src/include/switch_curl.h b/src/include/switch_curl.h new file mode 100644 index 0000000000..3820ba8693 --- /dev/null +++ b/src/include/switch_curl.h @@ -0,0 +1,81 @@ +/* + * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * Copyright (C) 2005-2010, 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): + * + * + * switch_curl.h + * + */ + +#ifndef __SWITCH_CURL_H +#define __SWITCH_CURL_H + +#include +#include + +static inline void switch_curl_init(void) +{ + int curl_count = switch_core_curl_count(NULL); + + if (curl_count == 0) { + curl_global_init(CURL_GLOBAL_ALL); +#if defined(HAVE_OPENSSL) + switch_ssl_init_ssl_locks(); +#endif + } + + curl_count++; + switch_core_curl_count(&curl_count); +} + +static inline void switch_curl_destroy() +{ + int curl_count = switch_core_curl_count(NULL); + + curl_count--; + + if (curl_count == 0) { + +#if defined(HAVE_OPENSSL) + switch_ssl_destroy_ssl_locks(); +#endif + curl_global_cleanup(); + } + switch_core_curl_count(&curl_count); +} + +#endif + + +/* 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/include/switch_ssl.h b/src/include/switch_ssl.h new file mode 100644 index 0000000000..4f72192c52 --- /dev/null +++ b/src/include/switch_ssl.h @@ -0,0 +1,107 @@ +/* + * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * Copyright (C) 2005-2010, 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): + * + * + * switch_ssl.h + * + */ + +#ifndef __SWITCH_SSL_H +#define __SWITCH_SSL_H + +#if defined(HAVE_OPENSSL) +#include + +static switch_mutex_t **ssl_mutexes; +static switch_memory_pool_t *ssl_pool = NULL; + + +static inline void switch_ssl_ssl_lock_callback(int mode, int type, char *file, int line) +{ + if (mode & CRYPTO_LOCK) { + switch_mutex_lock(ssl_mutexes[type]); + } + else { + switch_mutex_unlock(ssl_mutexes[type]); + } +} + +static inline unsigned long switch_ssl_ssl_thread_id(void) +{ + return (unsigned long) switch_thread_self(); +} + +static inline void switch_ssl_init_ssl_locks(void) +{ + + int ssl_count = switch_core_ssl_count(NULL); + int i, num; + + if (ssl_count == 0) { + num = CRYPTO_num_locks(); + + ssl_mutexes = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(switch_mutex_t*)); + switch_assert(ssl_mutexes != NULL); + + switch_core_new_memory_pool(&ssl_pool); + + for (i = 0; i < num; i++) { + switch_mutex_init(&(ssl_mutexes[i]), SWITCH_MUTEX_NESTED, ssl_pool); + switch_assert(ssl_mutexes[i] != NULL); + } + + CRYPTO_set_id_callback(switch_ssl_ssl_thread_id); + CRYPTO_set_locking_callback((void (*)(int, int, const char*, int))switch_ssl_ssl_lock_callback); + } + + ssl_count++; + switch_core_ssl_count(&ssl_count); +} + +static inline void switch_ssl_destroy_ssl_locks() +{ + int i; + int ssl_count = switch_core_ssl_count(NULL); + + ssl_count--; + + if (ssl_count == 0) { + CRYPTO_set_locking_callback(NULL); + for (i = 0; i < CRYPTO_num_locks(); i++) { + switch_mutex_destroy(ssl_mutexes[i]); + } + + OPENSSL_free(ssl_mutexes); + } + + switch_core_ssl_count(&ssl_count); + +} +#else +static inline void switch_ssl_init_ssl_locks(void) { return; } +static inline void switch_ssl_destroy_ssl_locks(void) { return; } +#endif + +#endif diff --git a/src/mod/.gitignore b/src/mod/.gitignore index b75dbcb9cf..73caeb6ca1 100644 --- a/src/mod/.gitignore +++ b/src/mod/.gitignore @@ -9,8 +9,6 @@ /applications/mod_conference/Makefile /applications/mod_db/Makefile /applications/mod_dptools/Makefile -/applications/mod_enum/Makefile -/applications/mod_enum/Makefile.in /applications/mod_enum/mod_enum.log /applications/mod_expr/Makefile /applications/mod_expr/Makefile.in diff --git a/src/mod/applications/mod_callcenter/mod_callcenter.c b/src/mod/applications/mod_callcenter/mod_callcenter.c index e3bf1797dc..c2c1c0c624 100644 --- a/src/mod/applications/mod_callcenter/mod_callcenter.c +++ b/src/mod/applications/mod_callcenter/mod_callcenter.c @@ -1985,12 +1985,12 @@ static int members_callback(void *pArg, int argc, char **argv, char **columnName /* Checking for cleanup Abandonded calls from the db */ if (!strcasecmp(member_state, cc_member_state2str(CC_MEMBER_STATE_ABANDONED))) { - long abandoned_epoch = atol(member_abandoned_epoch); + switch_time_t abandoned_epoch = atoll(member_abandoned_epoch); if (abandoned_epoch == 0) { - abandoned_epoch = atol(cbt.member_joined_epoch); + abandoned_epoch = atoll(cbt.member_joined_epoch); } /* Once we pass a certain point, we want to get rid of the abandoned call */ - if (abandoned_epoch + discard_abandoned_after < (long) local_epoch_time_now(NULL)) { + if (abandoned_epoch + discard_abandoned_after < local_epoch_time_now(NULL)) { sql = switch_mprintf("DELETE FROM members WHERE system = 'single_box' AND uuid = '%q' AND (abandoned_epoch = '%" SWITCH_TIME_T_FMT "' OR joined_epoch = '%q')", cbt.member_uuid, abandoned_epoch, cbt.member_joined_epoch); cc_execute_sql(NULL, sql, NULL); switch_safe_free(sql); diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c index b9b485a1b8..a69b18b578 100644 --- a/src/mod/applications/mod_conference/mod_conference.c +++ b/src/mod/applications/mod_conference/mod_conference.c @@ -200,7 +200,6 @@ typedef enum { EFLAG_FLOOR_CHANGE = (1 << 25), EFLAG_MUTE_DETECT = (1 << 26), EFLAG_RECORD = (1 << 27), - EFLAG_AUTO_GAIN_LEVEL = (1 << 28) } event_type_t; typedef struct conference_file_node { @@ -815,12 +814,19 @@ static switch_status_t conference_del_member(conference_obj_t *conference, confe switch_event_t *event; conference_file_node_t *member_fnode; switch_speech_handle_t *member_sh; + const char *exit_sound = NULL; switch_assert(conference != NULL); switch_assert(member != NULL); switch_thread_rwlock_wrlock(member->rwlock); + if (member->session && (exit_sound = switch_channel_get_variable(switch_core_session_get_channel(member->session), "conference_exit_sound"))) { + conference_play_file(conference, (char *)exit_sound, CONF_DEFAULT_LEADIN, + switch_core_session_get_channel(member->session), !switch_test_flag(conference, CFLAG_WAIT_MOD) ? 0 : 1); + } + + lock_member(member); member_fnode = member->fnode; member_sh = member->sh; @@ -910,7 +916,7 @@ static switch_status_t conference_del_member(conference_obj_t *conference, confe || (switch_test_flag(conference, CFLAG_DYNAMIC) && conference->count == 0)) { switch_set_flag(conference, CFLAG_DESTRUCT); } else { - if (conference->exit_sound && switch_test_flag(conference, CFLAG_EXIT_SOUND)) { + if (!exit_sound && conference->exit_sound && switch_test_flag(conference, CFLAG_EXIT_SOUND)) { conference_play_file(conference, conference->exit_sound, 0, switch_core_session_get_channel(member->session), 0); } if (conference->count == 1 && conference->alone_sound && !switch_test_flag(conference, CFLAG_WAIT_MOD)) { @@ -2056,7 +2062,7 @@ static void clear_avg(conference_member_t *member) static void check_agc_levels(conference_member_t *member) { - int x = 0, y = member->agc_volume_in_level; + int x = 0; if (!member->avg_score) return; @@ -2071,8 +2077,6 @@ static void check_agc_levels(conference_member_t *member) } if (x) { - switch_event_t *event; - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG7, "AGC %s:%d diff:%d level:%d cur:%d avg:%d vol:%d %s\n", member->conference->name, @@ -2080,17 +2084,6 @@ static void check_agc_levels(conference_member_t *member) member->score, member->avg_score, member->agc_volume_in_level, x > 0 ? "+++" : "---"); clear_avg(member); - - - if (test_eflag(member->conference, EFLAG_AUTO_GAIN_LEVEL) && - switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) { - conference_add_event_member_data(member, event); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action", "auto-gain-level"); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Old-Level", "%d", y); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "New-Level", "%d", member->agc_volume_in_level); - switch_event_fire(&event); - } - } } diff --git a/src/mod/applications/mod_lcr/mod_lcr.c b/src/mod/applications/mod_lcr/mod_lcr.c index fcb75ef4d5..c0d99dfc35 100644 --- a/src/mod/applications/mod_lcr/mod_lcr.c +++ b/src/mod/applications/mod_lcr/mod_lcr.c @@ -1664,7 +1664,7 @@ static void write_data(switch_stream_handle_t *stream, switch_bool_t as_xml, con SWITCH_STANDARD_API(dialplan_lcr_function) { - char *argv[4] = { 0 }; + char *argv[9] = { 0 }; int argc; char *mydata = NULL; //char *dialstring = NULL; @@ -1825,7 +1825,7 @@ SWITCH_STANDARD_API(dialplan_lcr_function) if (as_xml) { event_xml = switch_event_xmlize(current->fields, SWITCH_VA_NONE); event_str = switch_xml_toxml(event_xml, SWITCH_FALSE); - stream->write_function(stream, event_str); + stream->write_function(stream, "%s", event_str); switch_xml_free(event_xml); switch_safe_free(event_str); } diff --git a/src/mod/applications/mod_mongo/Makefile b/src/mod/applications/mod_mongo/Makefile new file mode 100644 index 0000000000..26687b5ac6 --- /dev/null +++ b/src/mod/applications/mod_mongo/Makefile @@ -0,0 +1,29 @@ +BASE=../../../.. + +MONGO_CXX_DRIVER_VERSION=v1.8 +MONGO_CXX_DRIVER_URL=http://downloads.mongodb.org/cxx-driver +MONGO_CXX_DRIVER_TARBALL=mongodb-linux-x86_64-$(MONGO_CXX_DRIVER_VERSION)-latest.tgz +MONGO_CXX_DRIVER_SRC=$(BASE)/libs/mongo-cxx-driver-$(MONGO_CXX_DRIVER_VERSION) +LIBMONGOCLIENT_A =$(MONGO_CXX_DRIVER_SRC)/libmongoclient.a + +LOCAL_SOURCES=mongo_conn.cpp +LOCAL_OBJS=mongo_conn.o + +LOCAL_CFLAGS=-I$(MONGO_CXX_DRIVER_SRC)/mongo +LOCAL_LIBADD=$(LIBMONGOCLIENT_A) +LOCAL_LDFLAGS=-lboost_thread -lboost_filesystem-mt -lboost_system-mt +MODDIR=$(shell pwd) + + +include $(BASE)/build/modmake.rules + +$(MONGO_CXX_DRIVER_SRC): + $(GETLIB) $(MONGO_CXX_DRIVER_URL) $(MONGO_CXX_DRIVER_TARBALL) + cd $(MONGO_CXX_DRIVER_SRC) && patch -p0 -i $(MODDIR)/fpic_hack.diff + $(TOUCH_TARGET) + + +$(LIBMONGOCLIENT_A): $(MONGO_CXX_DRIVER_SRC) + cd $(MONGO_CXX_DRIVER_SRC) && scons + $(TOUCH_TARGET) + diff --git a/src/mod/applications/mod_mongo/fpic_hack.diff b/src/mod/applications/mod_mongo/fpic_hack.diff new file mode 100644 index 0000000000..882f3c899a --- /dev/null +++ b/src/mod/applications/mod_mongo/fpic_hack.diff @@ -0,0 +1,11 @@ +--- SConstruct.orig 2011-04-28 19:00:36.000000000 +0200 ++++ SConstruct 2011-04-28 19:01:19.000000000 +0200 +@@ -45,7 +45,7 @@ + linux = True + + if nix: +- env.Append( CPPFLAGS=" -O3" ) ++ env.Append( CPPFLAGS=" -I../pcre -fPIC -O3" ) + env.Append( LIBS=["pthread"] ) + if linux: + env.Append( LINKFLAGS=" -Wl,--as-needed -Wl,-zdefs " ) diff --git a/src/mod/applications/mod_mongo/mod_mongo.cpp b/src/mod/applications/mod_mongo/mod_mongo.cpp new file mode 100644 index 0000000000..bb82c840e0 --- /dev/null +++ b/src/mod/applications/mod_mongo/mod_mongo.cpp @@ -0,0 +1,151 @@ +#include +#include "mod_mongo.h" + + +static struct { + mongo_connection_pool_t *conn_pool; +} globals; + + +static const char *SYNTAX = "mongo_find_one ns; query; fields"; + +SWITCH_STANDARD_API(mongo_find_one_function) +{ + switch_status_t status = SWITCH_STATUS_SUCCESS; + char *ns = NULL, *json_query = NULL, *json_fields = NULL; + char delim = ';'; + + ns = strdup(cmd); + switch_assert(ns != NULL); + + if ((json_query = strchr(ns, delim))) { + *json_query++ = '\0'; + if ((json_fields = strchr(json_query, delim))) { + *json_fields++ = '\0'; + } + } + + if (!zstr(ns) && !zstr(json_query) && !zstr(json_fields)) { + + DBClientConnection *conn = NULL; + + try { + BSONObj query = fromjson(json_query); + BSONObj fields = fromjson(json_fields); + + conn = mongo_connection_pool_get(globals.conn_pool); + if (conn) { + BSONObj res = conn->findOne(ns, Query(query), &fields); + mongo_connection_pool_put(globals.conn_pool, conn); + + stream->write_function(stream, "-OK\n%s\n", res.toString().c_str()); + } else { + stream->write_function(stream, "-ERR\nNo connection\n"); + } + } catch (DBException &e) { + if (conn) { + mongo_connection_destroy(&conn); + } + stream->write_function(stream, "-ERR\n%s\n", e.toString().c_str()); + } + + + } else { + stream->write_function(stream, "-ERR\n%s\n", SYNTAX); + } + + switch_safe_free(ns); + + return status; +} + +static switch_status_t config(void) +{ + const char *cf = "mongo.conf"; + switch_xml_t cfg, xml, settings, param; + switch_status_t status = SWITCH_STATUS_SUCCESS; + const char *host = "127.0.0.1"; + switch_size_t min_connections = 1, max_connections = 1; + + if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", cf); + return SWITCH_STATUS_GENERR; + } + + if ((settings = switch_xml_child(cfg, "settings"))) { + for (param = switch_xml_child(settings, "param"); param; param = param->next) { + char *var = (char *) switch_xml_attr_soft(param, "name"); + char *val = (char *) switch_xml_attr_soft(param, "value"); + int tmp; + + if (!strcmp(var, "host")) { + host = val; + } else if (!strcmp(var, "min-connections")) { + if ((tmp = atoi(val)) > 0) { + min_connections = tmp; + } + } else if (!strcmp(var, "max-connections")) { + if ((tmp = atoi(val)) > 0) { + max_connections = tmp; + } + } + } + } + + if (mongo_connection_pool_create(&globals.conn_pool, min_connections, max_connections, host) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Can't create connection pool\n"); + status = SWITCH_STATUS_GENERR; + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Mongo connection pool created [%s %d/%d]\n", host, (int)min_connections, (int)max_connections); + } + + switch_xml_free(xml); + + return status; +} + + +SWITCH_BEGIN_EXTERN_C + +SWITCH_MODULE_LOAD_FUNCTION(mod_mongo_load); +SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_mongo_shutdown); +SWITCH_MODULE_DEFINITION(mod_mongo, mod_mongo_load, mod_mongo_shutdown, NULL); + + +SWITCH_MODULE_LOAD_FUNCTION(mod_mongo_load) +{ + switch_api_interface_t *api_interface; + switch_application_interface_t *app_interface; + + *module_interface = switch_loadable_module_create_module_interface(pool, modname); + + memset(&globals, 0, sizeof(globals)); + + if (config() != SWITCH_STATUS_SUCCESS) { + return SWITCH_STATUS_TERM; + } + + SWITCH_ADD_API(api_interface, "mongo_find_one", "mongo", mongo_find_one_function, SYNTAX); + + return SWITCH_STATUS_SUCCESS; +} + +SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_mongo_shutdown) +{ + mongo_connection_pool_destroy(&globals.conn_pool); + return SWITCH_STATUS_SUCCESS; +} + +SWITCH_END_EXTERN_C + +/* 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_mongo/mod_mongo.h b/src/mod/applications/mod_mongo/mod_mongo.h new file mode 100644 index 0000000000..91c14bb29b --- /dev/null +++ b/src/mod/applications/mod_mongo/mod_mongo.h @@ -0,0 +1,38 @@ +#ifndef MOD_MONGO_H +#define MOD_MONGO_H + + +#include +#include +#include +#include + +using namespace mongo; + +typedef struct { + char *host; + + switch_size_t min_connections; + switch_size_t max_connections; + switch_size_t size; + switch_queue_t *connections; + switch_mutex_t *mutex; + switch_memory_pool_t *pool; + +} mongo_connection_pool_t; + + +switch_status_t mongo_connection_create(DBClientConnection **connection, const char *host); +void mongo_connection_destroy(DBClientConnection **conn); + +switch_status_t mongo_connection_pool_create(mongo_connection_pool_t **conn_pool, switch_size_t min_connections, switch_size_t max_connections, + const char *host); +void mongo_connection_pool_destroy(mongo_connection_pool_t **conn_pool); + + +DBClientConnection *mongo_connection_pool_get(mongo_connection_pool_t *conn_pool); +switch_status_t mongo_connection_pool_put(mongo_connection_pool_t *conn_pool, DBClientConnection *conn); + + +#endif + diff --git a/src/mod/applications/mod_mongo/mongo_conn.cpp b/src/mod/applications/mod_mongo/mongo_conn.cpp new file mode 100644 index 0000000000..ee702b8470 --- /dev/null +++ b/src/mod/applications/mod_mongo/mongo_conn.cpp @@ -0,0 +1,161 @@ +#include +#include "mod_mongo.h" + + /* + we could use the driver's connection pool, + if we could set the max connections (PoolForHost::setMaxPerHost) + + ScopedDbConnection scoped_conn("host"); + DBClientConnection *conn = dynamic_cast< DBClientConnection* >(&scoped_conn.conn()); + scoped_conn.done(); + */ + +switch_status_t mongo_connection_create(DBClientConnection **connection, const char *host) +{ + DBClientConnection *conn = new DBClientConnection(); + + try { + conn->connect(host); + } catch (DBException &e) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't connect to mongo [%s]\n", host); + return SWITCH_STATUS_GENERR; + } + + *connection = conn; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Connected to mongo [%s]\n", host); + + return SWITCH_STATUS_SUCCESS; +} + +void mongo_connection_destroy(DBClientConnection **conn) +{ + switch_assert(*conn != NULL); + delete *conn; + + *conn = NULL; +} + +switch_status_t mongo_connection_pool_create(mongo_connection_pool_t **conn_pool, switch_size_t min_connections, switch_size_t max_connections, + const char *host) +{ + switch_memory_pool_t *pool = NULL; + switch_status_t status = SWITCH_STATUS_SUCCESS; + mongo_connection_pool_t *cpool = NULL; + DBClientConnection *conn = NULL; + + if ((status = switch_core_new_memory_pool(&pool)) != SWITCH_STATUS_SUCCESS) { + return status; + } + + if (!(cpool = (mongo_connection_pool_t *)switch_core_alloc(pool, sizeof(mongo_connection_pool_t)))) { + switch_goto_status(SWITCH_STATUS_MEMERR, done); + } + + if ((status = switch_mutex_init(&cpool->mutex, SWITCH_MUTEX_NESTED, pool)) != SWITCH_STATUS_SUCCESS) { + goto done; + } + + if ((status = switch_queue_create(&cpool->connections, max_connections, pool)) != SWITCH_STATUS_SUCCESS) { + goto done; + } + + cpool->min_connections = min_connections; + cpool->max_connections = max_connections; + cpool->host = switch_core_strdup(pool, host); + + cpool->pool = pool; + + for (cpool->size = 0; cpool->size < min_connections; cpool->size++) { + + if (mongo_connection_create(&conn, host) == SWITCH_STATUS_SUCCESS) { + mongo_connection_pool_put(cpool, conn); + } else { + break; + } + } + + done: + + if (status == SWITCH_STATUS_SUCCESS) { + *conn_pool = cpool; + } else { + switch_core_destroy_memory_pool(&pool); + } + + + return status; +} + +void mongo_connection_pool_destroy(mongo_connection_pool_t **conn_pool) +{ + mongo_connection_pool_t *cpool = *conn_pool; + void *data = NULL; + + switch_assert(cpool != NULL); + + while (switch_queue_trypop(cpool->connections, &data) == SWITCH_STATUS_SUCCESS) { + mongo_connection_destroy((DBClientConnection **)&data); + } + + switch_mutex_destroy(cpool->mutex); + switch_core_destroy_memory_pool(&cpool->pool); + + *conn_pool = NULL; +} + + +DBClientConnection *mongo_connection_pool_get(mongo_connection_pool_t *conn_pool) +{ + DBClientConnection *conn = NULL; + void *data = NULL; + + switch_assert(conn_pool != NULL); + + switch_mutex_lock(conn_pool->mutex); + + if (switch_queue_trypop(conn_pool->connections, &data) == SWITCH_STATUS_SUCCESS) { + conn = (DBClientConnection *) data; + } else if (mongo_connection_create(&conn, conn_pool->host) == SWITCH_STATUS_SUCCESS) { + if (++conn_pool->size > conn_pool->max_connections) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Connection pool is empty. You may want to increase 'max-connections'\n"); + } + } + + switch_mutex_unlock(conn_pool->mutex); + +#ifdef MONGO_POOL_DEBUG + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "POOL get: size %d conn: %p\n", (int) switch_queue_size(conn_pool->connections), conn); +#endif + + return conn; +} + +switch_status_t mongo_connection_pool_put(mongo_connection_pool_t *conn_pool, DBClientConnection *conn) +{ + switch_status_t status = SWITCH_STATUS_SUCCESS; + + switch_assert(conn_pool != NULL); + switch_assert(conn != NULL); + + switch_mutex_lock(conn_pool->mutex); + if (conn_pool->size > conn_pool->max_connections) { +#ifdef MONGO_POOL_DEBUG + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "POOL: Destroy connection %p\n", conn); +#endif + mongo_connection_destroy(&conn); + conn_pool->size--; + } else { +#ifdef MONGO_POOL_DEBUG + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "POOL: push connection %p\n", conn); +#endif + status = switch_queue_push(conn_pool->connections, conn); + } + + switch_mutex_unlock(conn_pool->mutex); + +#ifdef MONGO_POOL_DEBUG + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "POOL: put size %d conn: %p\n", (int) switch_queue_size(conn_pool->connections), conn); +#endif + + return status; +} diff --git a/src/mod/applications/mod_nibblebill/mod_nibblebill.c b/src/mod/applications/mod_nibblebill/mod_nibblebill.c index 068a31f5f3..2cd772ece0 100755 --- a/src/mod/applications/mod_nibblebill/mod_nibblebill.c +++ b/src/mod/applications/mod_nibblebill/mod_nibblebill.c @@ -902,7 +902,7 @@ switch_state_handler_table_t nibble_state_handler = { /* on_hibernate */ NULL, /* on_reset */ NULL, /* on_park */ NULL, - /* on_reporting */ process_hangup, /* force billing event on b-leg if we can */ + /* on_reporting */ NULL, /* on_destroy */ NULL }; diff --git a/src/mod/codecs/mod_sangoma_codec/mod_sangoma_codec.c b/src/mod/codecs/mod_sangoma_codec/mod_sangoma_codec.c index b6cfbb0c54..c2d6ae40b5 100644 --- a/src/mod/codecs/mod_sangoma_codec/mod_sangoma_codec.c +++ b/src/mod/codecs/mod_sangoma_codec/mod_sangoma_codec.c @@ -96,7 +96,7 @@ vocallo_codec_t g_codec_map[] = /* manually initialized */ { SNGTC_CODEC_GSM_FR, IANA_GSM_A_8000_1, "GSM", "Sangoma GSM", 20, 13200, 20000, 160, 320, 33, 8000, 8000, 0 }, { SNGTC_CODEC_G723_1_63, IANA_G723_A_8000_1, "G723", "Sangoma G723", 90, 6300, 30000, 240, 480, 24, 8000, 8000, 0 }, - { SNGTC_CODEC_AMR_1220, IANA_AMR_WB_16000_1, "AMR", "Sangoma AMR", 20, 12200, 20000, 160, 320, 0, 8000, 8000, 0 }, + { SNGTC_CODEC_AMR_1220, IANA_AMR_A_8000_1, "AMR", "Sangoma AMR", 20, 12200, 20000, 160, 320, 0, 8000, 8000, 0 }, { SNGTC_CODEC_SIREN7_24, IANA_SIREN7, "G7221", "Sangoma G722.1", 20, 24000, 20000, 320, 640, 60, 16000, 16000, 0 }, { SNGTC_CODEC_SIREN7_32, IANA_SIREN7, "G7221", "Sangoma G722.1", 20, 32000, 20000, 320, 640, 80, 16000, 16000, 0 }, { SNGTC_CODEC_ILBC_133, IANA_ILBC_133_8000_1, "iLBC", "Sangoma iLBC", 30, 13300, 30000, 240, 480, 50, 8000, 8000, 0 }, @@ -131,6 +131,7 @@ struct codec_data { /* packet counters */ unsigned long tx; unsigned long rx; + unsigned long ticks; /* Lost packets */ long lastrxseqno; @@ -467,6 +468,8 @@ static switch_status_t switch_sangoma_encode(switch_codec_t *codec, switch_codec func_start_time = switch_micro_time_now(); } + sess->encoder.ticks++; + /* start assuming we will not encode anything */ *encoded_data_len = 0; @@ -547,7 +550,7 @@ static switch_status_t switch_sangoma_encode(switch_codec_t *codec, switch_codec continue; } - if (encoded_frame.datalen != codec->implementation->encoded_bytes_per_packet) { + if (codec->implementation->encoded_bytes_per_packet && encoded_frame.datalen != codec->implementation->encoded_bytes_per_packet) { /* seen when silence suppression is enabled */ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Ignoring encoded frame of %d bytes intead of %d bytes\n", encoded_frame.datalen, codec->implementation->encoded_bytes_per_packet); continue; @@ -619,7 +622,7 @@ static switch_status_t switch_sangoma_encode(switch_codec_t *codec, switch_codec sess->encoder.rtp_queue[sess->encoder.queue_rindex].datalen = 0; SAFE_INDEX_INC(sess->encoder.rtp_queue, sess->encoder.queue_rindex); sess->encoder.queue_size--; - if (*encoded_data_len != codec->implementation->encoded_bytes_per_packet) { + if (codec->implementation->encoded_bytes_per_packet && *encoded_data_len != codec->implementation->encoded_bytes_per_packet) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Returning odd encoded frame of %d bytes intead of %d bytes\n", *encoded_data_len, codec->implementation->encoded_bytes_per_packet); } } else { @@ -667,6 +670,7 @@ static switch_status_t switch_sangoma_decode(switch_codec_t *codec, /* codec ses } dbuf_linear = decoded_data; + sess->decoder.ticks++; /* start assuming we will not decode anything */ *decoded_data_len = 0; @@ -989,6 +993,7 @@ SWITCH_STANDARD_API(sangoma_function) stream->write_function(stream, "Rx %s at %d.%d.%d.%d:%d from %d.%d.%d.%d:%d\n\n", sess->impl->iananame, SNGTC_NIPV4(sess->encoder.reply.b.host_ip), sess->encoder.reply.b.host_udp_port, SNGTC_NIPV4(sess->encoder.reply.b.codec_ip), sess->encoder.reply.b.codec_udp_port); + stream->write_function(stream, "Ticks: %lu\n", sess->encoder.ticks); stream->write_function(stream, "-- Inbound Stats --\n"); stream->write_function(stream, "Rx Discarded: %lu\n", sess->encoder.rxdiscarded); @@ -1008,6 +1013,7 @@ SWITCH_STANDARD_API(sangoma_function) SNGTC_NIPV4(sess->decoder.reply.a.codec_ip), sess->decoder.reply.a.codec_udp_port); stream->write_function(stream, "Rx L16 at %d.%d.%d.%d:%d from %d.%d.%d.%d:%d\n\n", SNGTC_NIPV4(sess->decoder.reply.b.host_ip), sess->decoder.reply.b.host_udp_port, SNGTC_NIPV4(sess->decoder.reply.b.codec_ip), sess->decoder.reply.b.codec_udp_port); + stream->write_function(stream, "Ticks: %lu\n", sess->decoder.ticks); stream->write_function(stream, "-- Inbound Stats --\n"); stream->write_function(stream, "Rx Discarded: %lu\n", sess->decoder.rxdiscarded); diff --git a/src/mod/endpoints/mod_dingaling/mod_dingaling.c b/src/mod/endpoints/mod_dingaling/mod_dingaling.c index b0bfeada97..2db3660ccd 100644 --- a/src/mod/endpoints/mod_dingaling/mod_dingaling.c +++ b/src/mod/endpoints/mod_dingaling/mod_dingaling.c @@ -30,6 +30,7 @@ * */ #include +#include #include #include @@ -1399,7 +1400,7 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch { struct private_object *tech_pvt = NULL; switch_channel_t *channel = switch_core_session_get_channel(session); - int payload = 0; + //int payload = 0; tech_pvt = (struct private_object *) switch_core_session_get_private(session); switch_assert(tech_pvt != NULL); @@ -1443,7 +1444,7 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch - payload = tech_pvt->read_frame.payload; + //payload = tech_pvt->read_frame.payload; #if 0 elapsed = (unsigned int) ((switch_micro_time_now() - started) / 1000); @@ -1911,6 +1912,9 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dingaling_load) SWITCH_ADD_API(api_interface, "dingaling", "DingaLing Menu", dingaling, DINGALING_SYNTAX); SWITCH_ADD_CHAT(chat_interface, MDL_CHAT_PROTO, chat_send); + switch_ssl_init_ssl_locks(); + + /* indicate that the module should continue to be loaded */ return SWITCH_STATUS_SUCCESS; } @@ -2008,6 +2012,8 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_dingaling_shutdown) switch_safe_free(globals.codec_string); switch_safe_free(globals.codec_rates_string); + switch_ssl_destroy_ssl_locks(); + return SWITCH_STATUS_SUCCESS; } diff --git a/src/mod/endpoints/mod_h323/bugs b/src/mod/endpoints/mod_h323/bugs index 813c5c4c3a..ae2e0f1864 100644 --- a/src/mod/endpoints/mod_h323/bugs +++ b/src/mod/endpoints/mod_h323/bugs @@ -1,13 +1 @@ -faststart and codecs v CallProceeding due to h323plus, grep "Very Frustrating - S.H." in h323plus -source and uncomment commented lines. - - -exploration form developer of h323plus: - -Yes that should be mera. - -The problem is that Callproceeding does not always come from the remote it -may be generated by the gatekeeper. MERA where sending fast start elements -in the Call proceeding and connect. The call proceeding where not valid and -causing the media to fail. Normally (although valid) EP's do not set Fast -Start in Call proceeding so the code was disabled to resolve the MERA issue. +seems none for now \ No newline at end of file diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index c1431c28e9..c9ea6790b7 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -1241,6 +1241,7 @@ static void start_udptl(private_object_t *tech_pvt, switch_t38_options_t *t38_op switch_port_t remote_port = switch_rtp_get_remote_port(tech_pvt->rtp_session); const char *err, *val; + sofia_clear_flag(tech_pvt, TFLAG_NOTIMER_DURING_BRIDGE); switch_rtp_udptl_mode(tech_pvt->rtp_session); if (!t38_options || !t38_options->remote_ip) { @@ -1527,8 +1528,11 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi } if (sofia_test_flag(tech_pvt, TFLAG_NOTIMER_DURING_BRIDGE)) { - switch_rtp_set_flag(tech_pvt->rtp_session, SWITCH_RTP_FLAG_USE_TIMER); - switch_rtp_set_flag(tech_pvt->rtp_session, SWITCH_RTP_FLAG_NOBLOCK); + if (!switch_rtp_test_flag(tech_pvt->rtp_session, SWITCH_RTP_FLAG_UDPTL) && + !switch_rtp_test_flag(tech_pvt->rtp_session, SWITCH_RTP_FLAG_PROXY_MEDIA)) { + switch_rtp_set_flag(tech_pvt->rtp_session, SWITCH_RTP_FLAG_USE_TIMER); + switch_rtp_set_flag(tech_pvt->rtp_session, SWITCH_RTP_FLAG_NOBLOCK); + } sofia_clear_flag(tech_pvt, TFLAG_NOTIMER_DURING_BRIDGE); } @@ -2153,6 +2157,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi if (t38_options) { sofia_glue_set_image_sdp(tech_pvt, t38_options, 0); if (switch_rtp_ready(tech_pvt->rtp_session)) { + sofia_clear_flag(tech_pvt, TFLAG_NOTIMER_DURING_BRIDGE); switch_rtp_udptl_mode(tech_pvt->rtp_session); } } diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 3682260809..be24a00d98 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -4514,6 +4514,7 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status if (status == 200 && sofia_test_flag(tech_pvt, TFLAG_T38_PASSTHRU) && has_t38) { if (switch_rtp_ready(tech_pvt->rtp_session) && switch_rtp_ready(other_tech_pvt->rtp_session)) { + sofia_clear_flag(tech_pvt, TFLAG_NOTIMER_DURING_BRIDGE); switch_rtp_udptl_mode(tech_pvt->rtp_session); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Activating T38 Passthru\n"); } @@ -5558,13 +5559,6 @@ nua_handle_t *sofia_global_nua_handle_by_replaces(sip_replaces_t *replaces) const void *var; void *val; sofia_profile_t *profile; - switch_xml_t xml_root; - const char *err; - - if ((xml_root = switch_xml_open_root(1, &err))) { - switch_xml_free(xml_root); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Reload XML [%s]\n", err); - } switch_mutex_lock(mod_sofia_globals.hash_mutex); if (mod_sofia_globals.profile_hash) { diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index ab37ecd7f7..2724e5e562 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -2171,6 +2171,15 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session) if (!strncasecmp(url_str, "sips:", 5)) { s = url_str + 5; } + + /* tel: patch from jaybinks, added by MC + It compiles but I don't have a way to test it + */ + if (!strncasecmp(url_str, "tel:", 4)) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), + SWITCH_LOG_ERROR, "URL Error! tel: uri's not supported at this time\n"); + return SWITCH_STATUS_FALSE; + } if (!s) { s = url_str; } @@ -3009,6 +3018,21 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f if (remote_host && remote_port && !strcmp(remote_host, tech_pvt->remote_sdp_audio_ip) && remote_port == tech_pvt->remote_sdp_audio_port) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Audio params are unchanged for %s.\n", switch_channel_get_name(tech_pvt->channel)); + if (switch_rtp_ready(tech_pvt->rtp_session)) { + if (tech_pvt->audio_recv_pt != tech_pvt->agreed_pt) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, + "%s Set audio receive payload in Re-INVITE for non-matching dynamic PT to %u\n", + switch_channel_get_name(tech_pvt->channel), tech_pvt->audio_recv_pt); + + switch_rtp_set_recv_pt(tech_pvt->rtp_session, tech_pvt->audio_recv_pt); + } else { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, + "%s Setting audio receive payload in Re-INVITE to %u\n", + switch_channel_get_name(tech_pvt->channel), tech_pvt->audio_recv_pt); + switch_rtp_set_recv_pt(tech_pvt->rtp_session, tech_pvt->agreed_pt); + } + + } goto video; } else { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Audio params changed for %s from %s:%d to %s:%d\n", @@ -3436,9 +3460,9 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f if (!sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_RTP_AUTOADJ) && !switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE) && !((val = switch_channel_get_variable(tech_pvt->channel, "disable_rtp_auto_adjust")) && switch_true(val))) { - flags = (switch_rtp_flag_t) (SWITCH_RTP_FLAG_USE_TIMER | SWITCH_RTP_FLAG_AUTOADJ | SWITCH_RTP_FLAG_DATAWAIT | SWITCH_RTP_FLAG_RAW_WRITE); + flags = (switch_rtp_flag_t) (SWITCH_RTP_FLAG_AUTOADJ | SWITCH_RTP_FLAG_DATAWAIT | SWITCH_RTP_FLAG_RAW_WRITE); } else { - flags = (switch_rtp_flag_t) (SWITCH_RTP_FLAG_USE_TIMER | SWITCH_RTP_FLAG_DATAWAIT | SWITCH_RTP_FLAG_RAW_WRITE); + flags = (switch_rtp_flag_t) (SWITCH_RTP_FLAG_DATAWAIT | SWITCH_RTP_FLAG_RAW_WRITE); } if (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MEDIA)) { diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c index fdc3bd4d9a..3259808d4d 100644 --- a/src/mod/endpoints/mod_sofia/sofia_presence.c +++ b/src/mod/endpoints/mod_sofia/sofia_presence.c @@ -1417,6 +1417,11 @@ static int sofia_presence_sub_callback(void *pArg, int argc, char **argv, char * } if (!(nh = nua_handle_by_call_id(profile->nua, call_id))) { + + if (mod_sofia_globals.debug_presence > 0) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to find handle for call id %s\n", call_id); + } + goto end; } @@ -1468,12 +1473,18 @@ static int sofia_presence_sub_callback(void *pArg, int argc, char **argv, char * const char *astate = switch_str_nil(switch_event_get_header(helper->event, "astate")); const char *answer_state = switch_str_nil(switch_event_get_header(helper->event, "answer-state")); const char *dft_state; - const char *from_id = switch_str_nil(switch_event_get_header(helper->event, "Other-Leg-Caller-ID-Number")); + const char *from_id; const char *to_user = switch_str_nil(switch_event_get_header(helper->event, "variable_sip_to_user")); const char *from_user = switch_str_nil(switch_event_get_header(helper->event, "variable_sip_from_user")); char *clean_to_user = NULL; char *clean_from_user = NULL; int force_status = 0; + + if (!strcasecmp(direction, "inbound")) { + from_id = switch_str_nil(switch_event_get_header(helper->event, "Caller-Destination-Number")); + } else { + from_id = switch_str_nil(switch_event_get_header(helper->event, "Other-Leg-Caller-ID-Number")); + } #if 0 char *buf; switch_event_serialize(helper->event, &buf, SWITCH_FALSE); @@ -2175,58 +2186,79 @@ void sofia_presence_handle_sip_i_subscribe(int status, sip->sip_expires->ex_delta = 31536000; } - if (sofia_test_pflag(profile, PFLAG_MULTIREG)) { - sql = switch_mprintf("delete from sip_subscriptions where call_id='%q' " - "or (proto='%q' and sip_user='%q' and sip_host='%q' " - "and sub_to_user='%q' and sub_to_host='%q' and event='%q' and hostname='%q' " - "and contact='%q')", - call_id, proto, from_user, from_host, to_user, to_host, event, mod_sofia_globals.hostname, contact_str); - - } else { - sql = switch_mprintf("delete from sip_subscriptions where " - "proto='%q' and sip_user='%q' and sip_host='%q' and sub_to_user='%q' and sub_to_host='%q' and event='%q' and hostname='%q'", - proto, from_user, from_host, to_user, to_host, event, mod_sofia_globals.hostname); - } - - switch_mutex_lock(profile->ireg_mutex); - switch_assert(sql != NULL); - sofia_glue_actually_execute_sql(profile, sql, NULL); - switch_safe_free(sql); - - if (sub_state == nua_substate_terminated) { - sstr = switch_mprintf("terminated"); - } else { - sip_accept_t *ap = sip->sip_accept; - char accept[256] = ""; - full_agent = sip_header_as_string(profile->home, (void *) sip->sip_user_agent); - while (ap) { - switch_snprintf(accept + strlen(accept), sizeof(accept) - strlen(accept), "%s%s ", ap->ac_type, ap->ac_next ? "," : ""); - ap = ap->ac_next; - } - - sql = switch_mprintf("insert into sip_subscriptions " - "(proto,sip_user,sip_host,sub_to_user,sub_to_host,presence_hosts,event,contact,call_id,full_from," - "full_via,expires,user_agent,accept,profile_name,hostname,network_port,network_ip) " - "values ('%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q',%ld,'%q','%q','%q','%q','%d','%q')", - proto, from_user, from_host, to_user, to_host, profile->presence_hosts ? profile->presence_hosts : to_host, - event, contact_str, call_id, full_from, full_via, - //sofia_test_pflag(profile, PFLAG_MULTIREG) ? switch_epoch_time_now(NULL) + exp_delta : exp_delta * -1, + + if ((sub_state == nua_substate_active) && (switch_stristr("dialog", (const char *) event))) { + + sstr = switch_mprintf("active;expires=%ld", exp_delta); + + sql = switch_mprintf("update sip_subscriptions " + "set expires=%ld " + "where call_id='%q' and event='dialog' and hostname='%q' ", (long) switch_epoch_time_now(NULL) + (exp_delta * 2), - full_agent, accept, profile->name, mod_sofia_globals.hostname, np.network_port, np.network_ip); - - switch_assert(sql != NULL); + call_id, + mod_sofia_globals.hostname); + if (mod_sofia_globals.debug_presence > 0 || mod_sofia_globals.debug_sla > 0) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "%s SUBSCRIBE %s@%s %s@%s\n%s\n", - profile->name, from_user, from_host, to_user, to_host, sql); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, + "re-subscribe with dialog detected, sql: %s\n", sql); + } + + sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE); + } else { + if (sofia_test_pflag(profile, PFLAG_MULTIREG)) { + sql = switch_mprintf("delete from sip_subscriptions where call_id='%q' " + "or (proto='%q' and sip_user='%q' and sip_host='%q' " + "and sub_to_user='%q' and sub_to_host='%q' and event='%q' and hostname='%q' " + "and contact='%q')", + call_id, proto, from_user, from_host, to_user, to_host, event, mod_sofia_globals.hostname, contact_str); + + } else { + sql = switch_mprintf("delete from sip_subscriptions where " + "proto='%q' and sip_user='%q' and sip_host='%q' and sub_to_user='%q' and sub_to_host='%q' and event='%q' and hostname='%q'", + proto, from_user, from_host, to_user, to_host, event, mod_sofia_globals.hostname); } + switch_mutex_lock(profile->ireg_mutex); + switch_assert(sql != NULL); + sofia_glue_actually_execute_sql(profile, sql, NULL); + switch_safe_free(sql); - sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE); - sstr = switch_mprintf("active;expires=%ld", exp_delta); + if (sub_state == nua_substate_terminated) { + sstr = switch_mprintf("terminated"); + } else { + sip_accept_t *ap = sip->sip_accept; + char accept[256] = ""; + full_agent = sip_header_as_string(profile->home, (void *) sip->sip_user_agent); + while (ap) { + switch_snprintf(accept + strlen(accept), sizeof(accept) - strlen(accept), "%s%s ", ap->ac_type, ap->ac_next ? "," : ""); + ap = ap->ac_next; + } + + sql = switch_mprintf("insert into sip_subscriptions " + "(proto,sip_user,sip_host,sub_to_user,sub_to_host,presence_hosts,event,contact,call_id,full_from," + "full_via,expires,user_agent,accept,profile_name,hostname,network_port,network_ip) " + "values ('%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q',%ld,'%q','%q','%q','%q','%d','%q')", + proto, from_user, from_host, to_user, to_host, profile->presence_hosts ? profile->presence_hosts : to_host, + event, contact_str, call_id, full_from, full_via, + //sofia_test_pflag(profile, PFLAG_MULTIREG) ? switch_epoch_time_now(NULL) + exp_delta : exp_delta * -1, + (long) switch_epoch_time_now(NULL) + (exp_delta * 2), + full_agent, accept, profile->name, mod_sofia_globals.hostname, np.network_port, np.network_ip); + + switch_assert(sql != NULL); + + if (mod_sofia_globals.debug_presence > 0 || mod_sofia_globals.debug_sla > 0) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "%s SUBSCRIBE %s@%s %s@%s\n%s\n", + profile->name, from_user, from_host, to_user, to_host, sql); + } + + + sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE); + sstr = switch_mprintf("active;expires=%ld", exp_delta); } switch_mutex_unlock(profile->ireg_mutex); + } if (status < 200) { char *sticky = NULL; diff --git a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c index 900b9655ff..9a09e802c3 100644 --- a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c +++ b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c @@ -1106,7 +1106,7 @@ static int config(void) } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid encoding strategy '%s' specified\n", val); } - } else if (!strcasecmp(var, "apply-inbound-acl")) { + } else if (!strcasecmp(var, "apply-inbound-acl") && ! zstr(val)) { if (prefs.acl_count < MAX_ACL) { prefs.acl[prefs.acl_count++] = strdup(val); } else { diff --git a/src/mod/formats/mod_shout/mod_shout.c b/src/mod/formats/mod_shout/mod_shout.c index 377cfe520c..a4134db943 100644 --- a/src/mod/formats/mod_shout/mod_shout.c +++ b/src/mod/formats/mod_shout/mod_shout.c @@ -36,7 +36,7 @@ #include #include #include -#include +#include #define OUTSCALE 8192 * 2 #define MP3_SCACHE 16384 * 2 @@ -1480,7 +1480,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_shout_load) supported_formats[0] = "shout"; supported_formats[1] = "mp3"; - curl_global_init(CURL_GLOBAL_ALL); + switch_curl_init(); /* connect my internal structure to the blank pointer passed to me */ *module_interface = switch_loadable_module_create_module_interface(pool, modname); @@ -1507,7 +1507,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_shout_load) SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_shout_shutdown) { - curl_global_cleanup(); + switch_curl_destroy(); mpg123_exit(); return SWITCH_STATUS_SUCCESS; } diff --git a/src/mod/languages/mod_managed/freeswitch_wrap.cxx b/src/mod/languages/mod_managed/freeswitch_wrap.cxx index dbce0886cc..d1c0dfcb31 100644 --- a/src/mod/languages/mod_managed/freeswitch_wrap.cxx +++ b/src/mod/languages/mod_managed/freeswitch_wrap.cxx @@ -3023,6 +3023,35 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_switch_rtp_numbers_t_flush_packet_count_get } +SWIGEXPORT void SWIGSTDCALL CSharp_switch_rtp_numbers_t_largest_jb_size_set(void * jarg1, void * jarg2) { + switch_rtp_numbers_t *arg1 = (switch_rtp_numbers_t *) 0 ; + switch_size_t arg2 ; + switch_size_t *argp2 ; + + arg1 = (switch_rtp_numbers_t *)jarg1; + argp2 = (switch_size_t *)jarg2; + if (!argp2) { + SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, "Attempt to dereference null switch_size_t", 0); + return ; + } + arg2 = *argp2; + if (arg1) (arg1)->largest_jb_size = arg2; + +} + + +SWIGEXPORT void * SWIGSTDCALL CSharp_switch_rtp_numbers_t_largest_jb_size_get(void * jarg1) { + void * jresult ; + switch_rtp_numbers_t *arg1 = (switch_rtp_numbers_t *) 0 ; + switch_size_t result; + + arg1 = (switch_rtp_numbers_t *)jarg1; + result = ((arg1)->largest_jb_size); + jresult = new switch_size_t((switch_size_t &)result); + return jresult; +} + + SWIGEXPORT void * SWIGSTDCALL CSharp_new_switch_rtp_numbers_t() { void * jresult ; switch_rtp_numbers_t *result = 0 ; diff --git a/src/mod/languages/mod_managed/managed/swig.cs b/src/mod/languages/mod_managed/managed/swig.cs index d7a3aa9682..d06e9881d4 100644 --- a/src/mod/languages/mod_managed/managed/swig.cs +++ b/src/mod/languages/mod_managed/managed/swig.cs @@ -6597,6 +6597,12 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_rtp_numbers_t_flush_packet_count_get")] public static extern IntPtr switch_rtp_numbers_t_flush_packet_count_get(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_rtp_numbers_t_largest_jb_size_set")] + public static extern void switch_rtp_numbers_t_largest_jb_size_set(HandleRef jarg1, HandleRef jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_rtp_numbers_t_largest_jb_size_get")] + public static extern IntPtr switch_rtp_numbers_t_largest_jb_size_get(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_new_switch_rtp_numbers_t")] public static extern IntPtr new_switch_rtp_numbers_t(); @@ -29222,6 +29228,18 @@ public class switch_rtp_numbers_t : IDisposable { } } + public SWIGTYPE_p_switch_size_t largest_jb_size { + set { + freeswitchPINVOKE.switch_rtp_numbers_t_largest_jb_size_set(swigCPtr, SWIGTYPE_p_switch_size_t.getCPtr(value)); + if (freeswitchPINVOKE.SWIGPendingException.Pending) throw freeswitchPINVOKE.SWIGPendingException.Retrieve(); + } + get { + SWIGTYPE_p_switch_size_t ret = new SWIGTYPE_p_switch_size_t(freeswitchPINVOKE.switch_rtp_numbers_t_largest_jb_size_get(swigCPtr), true); + if (freeswitchPINVOKE.SWIGPendingException.Pending) throw freeswitchPINVOKE.SWIGPendingException.Retrieve(); + return ret; + } + } + public switch_rtp_numbers_t() : this(freeswitchPINVOKE.new_switch_rtp_numbers_t(), true) { } diff --git a/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c b/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c index 7341a2b1e1..a09cfdf02a 100644 --- a/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c +++ b/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c @@ -35,7 +35,7 @@ #include "mod_spidermonkey.h" #ifdef HAVE_CURL -#include +#include #endif static int foo = 0; static jsval check_hangup_hook(struct js_session *jss, jsval * rp); @@ -2551,7 +2551,6 @@ static JSBool js_fetchurl_file(JSContext * cx, JSObject * obj, uintN argc, jsval url = JS_GetStringBytes(JS_ValueToString(cx, argv[0])); filename = JS_GetStringBytes(JS_ValueToString(cx, argv[1])); - curl_global_init(CURL_GLOBAL_ALL); curl_handle = curl_easy_init(); if (!strncasecmp(url, "https", 5)) { curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0); @@ -2600,7 +2599,6 @@ static JSBool js_fetchurl(JSContext * cx, JSObject * obj, uintN argc, jsval * ar JS_ValueToInt32(cx, argv[1], &buffer_size); } - curl_global_init(CURL_GLOBAL_ALL); curl_handle = curl_easy_init(); if (!strncasecmp(url, "https", 5)) { curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0); @@ -3803,7 +3801,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_spidermonkey_load) SWITCH_ADD_APP(app_interface, "javascript", "Launch JS ivr", "Run a javascript ivr on a channel", js_dp_function, "