freetdm - ISDN support for sending Network Specific Facility

This commit is contained in:
David Yat Sin 2012-01-16 17:14:59 -05:00
parent 2453a4e709
commit 44ed952a7b
6 changed files with 157 additions and 2 deletions

View File

@ -499,6 +499,7 @@ ftdm_status_t get_calling_subaddr(ftdm_channel_t *ftdmchan, CgPtySad *cgPtySad);
ftdm_status_t get_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd);
ftdm_status_t get_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr);
ftdm_status_t get_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, uint8_t data_len);
ftdm_status_t get_network_specific_fac(ftdm_channel_t *ftdmchan, NetFac *netFac);
ftdm_status_t set_calling_num(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb);
ftdm_status_t set_calling_num2(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb);
@ -508,6 +509,7 @@ ftdm_status_t set_calling_name(ftdm_channel_t *ftdmchan, ConEvnt *conEvnt);
ftdm_status_t set_calling_subaddr(ftdm_channel_t *ftdmchan, CgPtySad *cgPtySad);
ftdm_status_t set_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd, ftdm_sngisdn_progind_t prog_ind);
ftdm_status_t set_bear_cap_ie(ftdm_channel_t *ftdmchan, BearCap *bearCap);
ftdm_status_t set_network_specific_fac(ftdm_channel_t *ftdmchan, NetFac *netFac);
ftdm_status_t set_chan_id_ie(ftdm_channel_t *ftdmchan, ChanId *chanId);
ftdm_status_t set_restart_ind_ie(ftdm_channel_t *ftdmchan, RstInd *rstInd);
ftdm_status_t set_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr);

View File

@ -135,6 +135,7 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
get_prog_ind_ie(ftdmchan, &conEvnt->progInd);
get_facility_ie(ftdmchan, &conEvnt->facilityStr);
get_calling_name(ftdmchan, conEvnt);
get_network_specific_fac(ftdmchan, &conEvnt->netFac[0]);
ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Incoming call: Called No:[%s] Calling No:[%s]\n", ftdmchan->caller_data.dnis.digits, ftdmchan->caller_data.cid_num.digits);

View File

@ -69,6 +69,7 @@ void sngisdn_snd_setup(ftdm_channel_t *ftdmchan)
set_calling_subaddr(ftdmchan, &conEvnt.cgPtySad);
set_redir_num(ftdmchan, &conEvnt.redirNmb);
set_calling_name(ftdmchan, &conEvnt);
set_network_specific_fac(ftdmchan, &conEvnt.netFac[0]);
/* set_facility_ie will overwrite Calling Name for NI-2 if user specifies custom Facility IE */
set_facility_ie(ftdmchan, &conEvnt.facilityStr);

View File

@ -43,6 +43,15 @@ SNGISDN_STR2ENUM(ftdm_str2ftdm_sngisdn_progind_descr, ftdm_sngisdn_progind_descr
SNGISDN_ENUM_NAMES(SNGISDN_PROGIND_LOC_NAMES, SNGISDN_PROGIND_LOC_STRINGS)
SNGISDN_STR2ENUM(ftdm_str2ftdm_sngisdn_progind_loc, ftdm_sngisdn_progind_loc2str, ftdm_sngisdn_progind_loc_t, SNGISDN_PROGIND_LOC_NAMES, SNGISDN_PROGIND_LOC_INVALID)
SNGISDN_ENUM_NAMES(SNGISDN_NETSPECFAC_TYPE_NAMES, SNGISDN_NETSPECFAC_TYPE_STRINGS)
SNGISDN_STR2ENUM(ftdm_str2ftdm_sngisdn_netspecfac_type, ftdm_sngisdn_netspecfac_type2str, ftdm_sngisdn_netspecfac_type_t, SNGISDN_NETSPECFAC_TYPE_NAMES, SNGISDN_NETSPECFAC_TYPE_INVALID)
SNGISDN_ENUM_NAMES(SNGISDN_NETSPECFAC_PLAN_NAMES, SNGISDN_NETSPECFAC_PLAN_STRINGS)
SNGISDN_STR2ENUM(ftdm_str2ftdm_sngisdn_netspecfac_plan, ftdm_sngisdn_netspecfac_plan2str, ftdm_sngisdn_netspecfac_plan_t, SNGISDN_NETSPECFAC_PLAN_NAMES, SNGISDN_NETSPECFAC_PLAN_INVALID)
SNGISDN_ENUM_NAMES(SNGISDN_NETSPECFAC_SPEC_NAMES, SNGISDN_NETSPECFAC_SPEC_STRINGS)
SNGISDN_STR2ENUM(ftdm_str2ftdm_sngisdn_netspecfac_spec, ftdm_sngisdn_netspecfac_spec2str, ftdm_sngisdn_netspecfac_spec_t, SNGISDN_NETSPECFAC_SPEC_NAMES, SNGISDN_NETSPECFAC_SPEC_INVALID)
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);
ftdm_status_t get_calling_name_from_usr_usr(ftdm_channel_t *ftdmchan, UsrUsr *usrUsr);
@ -71,6 +80,28 @@ ftdm2trillium_t ton_codes[] = {
{FTDM_TON_RESERVED, IN_TON_EXT},
};
ftdm2trillium_t nsf_spec_codes[] = {
{SNGISDN_NETSPECFAC_SPEC_ACCUNET, 0xe6},
{SNGISDN_NETSPECFAC_SPEC_MEGACOM, 0xe3},
{SNGISDN_NETSPECFAC_SPEC_MEGACOM_800, 0xe2},
{SNGISDN_NETSPECFAC_SPEC_SDDN, 0xe1},
{SNGISDN_NETSPECFAC_SPEC_INVALID, 0x00},
};
ftdm2trillium_t nsf_type_codes[] = {
{SNGISDN_NETSPECFAC_TYPE_USER_SPEC, 0x00},
{SNGISDN_NETSPECFAC_TYPE_NATIONAL_NETWORK_IDENT, 0x02},
{SNGISDN_NETSPECFAC_TYPE_INTERNATIONAL_NETWORK_IDENT, 0x03},
{SNGISDN_NETSPECFAC_TYPE_INVALID, 0x00},
};
ftdm2trillium_t nsf_plan_codes[] = {
{SNGISDN_NETSPECFAC_PLAN_UNKNOWN, 0x00},
{SNGISDN_NETSPECFAC_PLAN_CARRIER_IDENT, 0x01},
{SNGISDN_NETSPECFAC_PLAN_DATA_NETWORK_IDENT, 0x03},
{SNGISDN_NETSPECFAC_PLAN_INVALID, 0x00},
};
static uint8_t get_trillium_val(ftdm2trillium_t *vals, uint8_t ftdm_val, uint8_t default_val)
{
ftdm2trillium_t *val = vals;
@ -530,6 +561,29 @@ ftdm_status_t get_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd)
}
ftdm_status_t get_network_specific_fac(ftdm_channel_t *ftdmchan, NetFac *netFac)
{
if (!netFac->eh.pres) {
return FTDM_FAIL;
}
if (netFac->netFacSpec.pres == PRSNT_NODEF) {
char digits_string [32];
memcpy(digits_string, (const char*)netFac->netFacSpec.val, netFac->netFacSpec.len);
digits_string[netFac->netFacSpec.len] = '\0';
sngisdn_add_var((sngisdn_chan_data_t*)ftdmchan->call_data, "isdn.netFac.spec", digits_string);
}
if (netFac->typeNetId.pres == PRSNT_NODEF) {
sngisdn_add_var((sngisdn_chan_data_t*)ftdmchan->call_data, "isdn.netFac.type", ftdm_sngisdn_netspecfac_type2str(get_ftdm_val(nsf_type_codes, netFac->typeNetId.val, 0x00)));
}
if (netFac->netIdPlan.pres == PRSNT_NODEF) {
sngisdn_add_var((sngisdn_chan_data_t*)ftdmchan->call_data, "isdn.netFac.plan", ftdm_sngisdn_netspecfac_type2str(get_ftdm_val(nsf_plan_codes, netFac->netIdPlan.val, 0x00)));
}
return FTDM_SUCCESS;
}
ftdm_status_t set_calling_num(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb)
{
ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
@ -900,6 +954,67 @@ ftdm_status_t set_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd, ftdm_s
return FTDM_SUCCESS;
}
ftdm_status_t set_network_specific_fac(ftdm_channel_t *ftdmchan, NetFac *netFac)
{
const char *str = NULL;
str = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "isdn.netFac.spec");
if (ftdm_strlen_zero(str)) {
/* Network-specific facility specification is mandatory, cannot send IE
without it */
return FTDM_SUCCESS;
} else {
ftdm_sngisdn_netspecfac_spec_t spec = ftdm_str2ftdm_sngisdn_netspecfac_spec(str);
netFac->eh.pres = PRSNT_NODEF;
netFac->netFacSpec.pres = PRSNT_NODEF;
if (spec == SNGISDN_NETSPECFAC_SPEC_INVALID) {
int byte = 0;
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Non-standard NSF specified:%s\n", str);
if (sscanf(str, "%x", &byte) == 1) {
netFac->netFacSpec.val[0] = byte & 0xFF;
}
netFac->netFacSpec.len = 1;
} else {
/* User is using one of the pre-specified NSF's */
netFac->netFacSpec.val[0] = get_trillium_val(nsf_spec_codes, spec, 0x00);
netFac->netFacSpec.len = 1;
}
}
netFac->lenNetId.pres = PRSNT_NODEF;
netFac->lenNetId.val = 0;
str = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "isdn.netFac.type");
if (!ftdm_strlen_zero(str)) {
netFac->typeNetId.pres = PRSNT_NODEF;
netFac->typeNetId.val = ftdm_str2ftdm_sngisdn_netspecfac_type(str);
}
str = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "isdn.netFac.plan");
if (!ftdm_strlen_zero(str)) {
netFac->netIdPlan.pres = PRSNT_NODEF;
netFac->netIdPlan.val = ftdm_str2ftdm_sngisdn_netspecfac_plan(str);
}
if (netFac->netIdPlan.pres == PRSNT_NODEF || netFac->typeNetId.pres == PRSNT_NODEF) {
netFac->lenNetId.val++;
}
str = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "isdn.netFac.ident");
if (!ftdm_strlen_zero(str)) {
netFac->lenNetId.val++;
netFac->netId.pres = PRSNT_NODEF;
memcpy(netFac->netId.val, str, strlen(str));
}
return FTDM_SUCCESS;
}
ftdm_status_t set_user_to_user_ie(ftdm_channel_t *ftdmchan, UsrUsr *usrUsr)
{
sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data;

View File

@ -771,7 +771,7 @@ uint32_t sngisdn_decode_ie(char *str, uint32_t *str_len, uint8_t current_codeset
default:
{
*str_len += sprintf(&str[*str_len], "Undecoded");
print_hex_dump((char*)str, str_len, data, index_start, index_end);
print_hex_dump((char*)str, str_len, data, index_start, index_end + 1);
}
break;
}

View File

@ -101,6 +101,42 @@ typedef enum {
#define SNGISDN_PROGIND_LOC_STRINGS "user", "private-net-local-user", "public-net-local-user", "transit-network", "public-net-remote-user", "private-net-remote-user", "beyond-interworking", "invalid"
SNGISDN_STR2ENUM_P(ftdm_str2ftdm_sngisdn_progind_loc, ftdm_sngisdn_progind_loc2str, ftdm_sngisdn_progind_loc_t);
typedef enum {
/* User Specified */
SNGISDN_NETSPECFAC_TYPE_USER_SPEC,
/* National network identification */
SNGISDN_NETSPECFAC_TYPE_NATIONAL_NETWORK_IDENT,
/* International network identification */
SNGISDN_NETSPECFAC_TYPE_INTERNATIONAL_NETWORK_IDENT,
/* Invalid */
SNGISDN_NETSPECFAC_TYPE_INVALID,
} ftdm_sngisdn_netspecfac_type_t;
#define SNGISDN_NETSPECFAC_TYPE_STRINGS "user-specified", "national-network-identification", "national-network-identification", "invalid"
SNGISDN_STR2ENUM_P(ftdm_str2ftdm_sngisdn_netspecfac_type, ftdm_sngisdn_netspecfac_type2str, ftdm_sngisdn_netspecfac_type_t);
typedef enum {
/* Unknown */
SNGISDN_NETSPECFAC_PLAN_UNKNOWN,
/* Carrier Identification Code */
SNGISDN_NETSPECFAC_PLAN_CARRIER_IDENT,
/* Data network identification code */
SNGISDN_NETSPECFAC_PLAN_DATA_NETWORK_IDENT,
/* Invalid */
SNGISDN_NETSPECFAC_PLAN_INVALID,
} ftdm_sngisdn_netspecfac_plan_t;
#define SNGISDN_NETSPECFAC_PLAN_STRINGS "unknown", "carrier-identification", "data-network-identification", "invalid"
SNGISDN_STR2ENUM_P(ftdm_str2ftdm_sngisdn_netspecfac_plan, ftdm_sngisdn_netspecfac_plan2str, ftdm_sngisdn_netspecfac_plan_t);
typedef enum {
/* Unknown */
SNGISDN_NETSPECFAC_SPEC_ACCUNET,
SNGISDN_NETSPECFAC_SPEC_MEGACOM,
SNGISDN_NETSPECFAC_SPEC_MEGACOM_800,
SNGISDN_NETSPECFAC_SPEC_SDDN,
SNGISDN_NETSPECFAC_SPEC_INVALID,
} ftdm_sngisdn_netspecfac_spec_t;
#define SNGISDN_NETSPECFAC_SPEC_STRINGS "accunet", "megacom", "megacom-800", "sddn", "invalid"
SNGISDN_STR2ENUM_P(ftdm_str2ftdm_sngisdn_netspecfac_spec, ftdm_sngisdn_netspecfac_spec2str, ftdm_sngisdn_netspecfac_spec_t);
#endif /* __FTMOD_SANGOMA_ISDN_USER_H__*/