]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
freetdm - ISDN support for sending Network Specific Facility
authorDavid Yat Sin <dyatsin@sangoma.com>
Mon, 16 Jan 2012 22:14:59 +0000 (17:14 -0500)
committerDavid Yat Sin <dyatsin@sangoma.com>
Mon, 16 Jan 2012 22:14:59 +0000 (17:14 -0500)
libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h
libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c
libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c
libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c
libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.c
libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_user.h

index a07f07e04608c49c1bbee0ca1855cab31b56701b..92054b88694e23544fa67e6ca1e68bfe015270e1 100644 (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);
index e95a582a45379be5d7c77c0d787bf71c7878cc63..5ff0b2a23f2d09f25cc89c7c4e3674b88743a5af 100644 (file)
@@ -133,8 +133,9 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
                        get_redir_num(ftdmchan, &conEvnt->redirNmb);
                        get_calling_subaddr(ftdmchan, &conEvnt->cgPtySad);
                        get_prog_ind_ie(ftdmchan, &conEvnt->progInd);
-                       get_facility_ie(ftdmchan, &conEvnt->facilityStr);                       
+                       get_facility_ie(ftdmchan, &conEvnt->facilityStr);
                        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);
 
index 7083fe25eceafdca7e90426bc00437f5a37bdbad..327f1a7220d7d0af8c4de39e497648547c9f101f 100644 (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);
index 70028e647d58ffed1fab1626fe0de202dac83093..bc53a42a7a8f1edb44bdae3590c6af12b2fabc54 100644 (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;
index 467ac7f9d8629522e7f98c2bd69fbf72fce05176..52c4f4d321278f4c043dd441d77e05666ecd4aca 100644 (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;
        }
index 5d94e6c6203def77d0ccbcad5a5b9b2e1ba4a2bb..85cbc9b183b138b80bf9912df58a4560daa8cf61 100644 (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__*/