]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
freetdm: ss7 - added support for sending sub-address values
authorKonrad Hammel <konrad@sangoma.com>
Fri, 15 Oct 2010 17:40:20 +0000 (13:40 -0400)
committerKonrad Hammel <konrad@sangoma.com>
Fri, 15 Oct 2010 17:41:31 +0000 (13:41 -0400)
freetdm: ss7 - switch back to sending RSC at startup rather then GRS

libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c
libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h
libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c
libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c

index 30cb31691d70ca824e2181e5dff4ddf7b6ec2756..cff97118145b1a8441ff0ba46251f8c624731200 100644 (file)
@@ -1332,7 +1332,7 @@ static ftdm_status_t ftdm_sangoma_ss7_start(ftdm_span_t * span)
                        sngss7_clear_flag(sngss7_info, FLAG_INFID_PAUSED);
                        sngss7_set_flag(sngss7_info, FLAG_INFID_RESUME);
                }
-#if 1
+#if 0
                /* throw the grp reset flag */
                sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_TX);
                if (x == 1) {
index a358236ed0d703d18ddc5ed9b07ce00ae5413ca8..5de237dcbfa49a20b52f907ea5126bee0e96e584 100644 (file)
@@ -58,6 +58,8 @@
 
 #define SNGSS7_EVENT_QUEUE_SIZE        100
 
+#define MAX_SIZEOF_SUBADDR_IE  24      /* as per Q931 4.5.9 */
+
 typedef enum {
        SNGSS7_CON_IND_EVENT = 0,
        SNGSS7_CON_CFM_EVENT,
@@ -83,6 +85,11 @@ typedef enum {
        SNGSS7_PAUSED   = (1 << 7)
 } sng_flag_t;
 
+typedef enum {
+       SNG_CALLED                      = 1,
+       SNG_CALLING                     = 2
+} sng_addr_type_t;
+
 typedef struct sng_mtp_link {
        char                    name[MAX_NAME_LEN];
        uint32_t                id;
@@ -579,6 +586,8 @@ ftdm_status_t clear_rx_grs_data(sngss7_chan_data_t *sngss7_info);
 ftdm_status_t clear_rx_gra_data(sngss7_chan_data_t *sngss7_info);
 ftdm_status_t clear_tx_grs_data(sngss7_chan_data_t *sngss7_info);
 
+ftdm_status_t encode_subAddrIE_nsap(const char *subAddr, char *subAddrIE, int type);
+ftdm_status_t encode_subAddrIE_nat(const char *subAddr, char *subAddrIE, int type);
 
 /* in ftmod_sangoma_ss7_timers.c */
 void handle_isup_t35(void *userdata);
index 973fbf47c7f4c3fd0c3061ddcb7606609e706114..3571a9ef0a8235715240e45b9390b0bc637692e8 100644 (file)
@@ -76,6 +76,9 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
        sngss7_chan_data_t      *sngss7_info = ftdmchan->call_data;;
        const char                      *clg_nadi = NULL;
        const char                      *cld_nadi = NULL;
+       const char                      *clg_subAddr = NULL;
+       const char                      *cld_subAddr = NULL;
+       char                            subAddrIE[MAX_SIZEOF_SUBADDR_IE];
        SiConEvnt                       iam;
        
        sngss7_info->suInstId   = get_unique_id ();
@@ -186,7 +189,7 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
        /* check if the user would like a custom NADI value for the calling Pty Num */
        clg_nadi = ftdm_channel_get_var(ftdmchan, "ss7_clg_nadi");
        if ((clg_nadi != NULL) && (*clg_nadi)) {
-               SS7_DEBUG_CHAN(ftdmchan,"Found user supplied NADI value \"%s\"\n", clg_nadi);
+               SS7_DEBUG_CHAN(ftdmchan,"Found user supplied Calling NADI value \"%s\"\n", clg_nadi);
                iam.cgPtyNum.natAddrInd.val     = atoi(clg_nadi);
        } else {
                iam.cgPtyNum.natAddrInd.val     = g_ftdm_sngss7_data.cfg.isupIntf[sngss7_info->circuit->infId].clg_nadi;
@@ -195,14 +198,93 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
 
        cld_nadi = ftdm_channel_get_var(ftdmchan, "ss7_cld_nadi");
        if ((cld_nadi != NULL) && (*cld_nadi)) {
-               SS7_DEBUG_CHAN(ftdmchan,"Found user supplied NADI value \"%s\"\n", cld_nadi);
+               SS7_DEBUG_CHAN(ftdmchan,"Found user supplied Called NADI value \"%s\"\n", cld_nadi);
                iam.cdPtyNum.natAddrInd.val     = atoi(cld_nadi);
        } else {
                iam.cdPtyNum.natAddrInd.val     = g_ftdm_sngss7_data.cfg.isupIntf[sngss7_info->circuit->infId].cld_nadi;
                SS7_DEBUG_CHAN(ftdmchan,"No user supplied NADI value found for CLD, using \"%d\"\n", iam.cdPtyNum.natAddrInd.val);
+       }
 
+       /* check if the user would like us to send a clg_sub-address */
+       clg_subAddr = ftdm_channel_get_var(ftdmchan, "ss7_clg_subaddr");
+       if ((clg_subAddr != NULL) && (*clg_subAddr)) {
+               SS7_DEBUG_CHAN(ftdmchan,"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:
+                       SS7_ERROR_CHAN(ftdmchan,"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 (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') */
        }
 
+       /* check if the user would like us to send a cld_sub-address */
+       cld_subAddr = ftdm_channel_get_var(ftdmchan, "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,
index 41db1fe140f5cd29fba06de3dee951bddff06d1a..718663950af817288a6abf8063709f143db46f9a 100644 (file)
@@ -71,6 +71,9 @@ ftdm_status_t clear_tx_rsc_flags(sngss7_chan_data_t *sngss7_info);
 ftdm_status_t clear_rx_grs_data(sngss7_chan_data_t *sngss7_info);
 ftdm_status_t clear_rx_gra_data(sngss7_chan_data_t *sngss7_info);
 ftdm_status_t clear_tx_grs_data(sngss7_chan_data_t *sngss7_info);
+
+ftdm_status_t encode_subAddrIE_nsap(const char *subAddr, char *subAddrIE, int type);
+ftdm_status_t encode_subAddrIE_nat(const char *subAddr, char *subAddrIE, int type);
 /******************************************************************************/
 
 /* FUNCTIONS ******************************************************************/
@@ -884,6 +887,214 @@ ftdm_status_t clear_tx_rsc_flags(sngss7_chan_data_t *sngss7_info)
 }
 
 /******************************************************************************/
+ftdm_status_t encode_subAddrIE_nsap(const char *subAddr, char *subAddrIE, int type)
+{
+       /* Q931 4.5.9 
+        * 8    7       6       5       4       3       2       1       (octet)
+        *
+        * 0    1       1       1       0       0       0       1       (spare 8) ( IE id 1-7)
+        * X    X       X       X       X       X       X       X       (length of IE contents)
+        * 1    0       0       0       Z       0       0       0       (ext 8) (NSAP type 5-7) (odd/even 4) (spare 1-3)
+        * X    X       X       X       X       X       X       X       (sub address encoded in ia5)
+        */
+
+       int     x = 0;
+       int p = 0;
+       int len = 0;
+       char tmp[2];
+
+       /* initalize the second element of tmp to \0 so that atoi doesn't go to far */
+       tmp[1]='\0';
+
+       /* set octet 1 aka IE id */
+       p = 0;
+       switch(type) {
+       /**************************************************************************/
+       case SNG_CALLED:                                                /* called party sub address */
+               subAddrIE[p] = 0x71;
+               break;
+       /**************************************************************************/
+       case SNG_CALLING:                                               /* calling party sub address */
+               subAddrIE[p] = 0x6d;
+               break;
+       /**************************************************************************/
+       default:                                                                /* not good */
+               SS7_ERROR("Sub-Address type is invalid: %d\n", type);
+               return FTDM_FAIL;
+               break;
+       /**************************************************************************/
+       } /* switch(type) */
+
+       /* set octet 3 aka type and o/e */
+       p = 2;
+       subAddrIE[p] = 0x80;
+
+       /* set the subAddrIE pointer octet 4 */
+       p = 3;
+
+       /* loop through all digits in subAddr and insert them into subAddrIE */
+       while (subAddr[x] != '\0') {
+
+               /* grab a character */
+               tmp[0] = subAddr[x];
+
+               /* confirm it is a digit */
+               if (!isdigit(tmp[0])) {
+                       /* move to the next character in subAddr */
+                       x++;
+
+                       /* restart the loop */
+                       continue;
+               }
+
+               /* convert the character to IA5 encoding and write into subAddrIE */
+               subAddrIE[p] = atoi(&tmp[0]);   /* lower nibble is the digit */
+               subAddrIE[p] |= 0x3 << 4;               /* upper nibble is 0x3 */
+
+               /* increment address length counter */
+               len++;
+
+               /* increment the subAddrIE pointer */
+               p++;
+
+               /* move to the next character in subAddr */
+               x++;
+
+       } /* while (subAddr[x] != '\0') */
+
+       /* set octet 2 aka length of subaddr */
+       p = 1;
+       subAddrIE[p] = len + 1;
+
+
+       return FTDM_SUCCESS;
+}
+
+/******************************************************************************/
+ftdm_status_t encode_subAddrIE_nat(const char *subAddr, char *subAddrIE, int type)
+{
+       /* Q931 4.5.9 
+        * 8    7       6       5       4       3       2       1       (octet)
+        *
+        * 0    1       1       1       0       0       0       1       (spare 8) ( IE id 1-7)
+        * X    X       X       X       X       X       X       X       (length of IE contents)
+        * 1    0       0       0       Z       0       0       0       (ext 8) (NSAP type 5-7) (odd/even 4) (spare 1-3)
+        * X    X       X       X       X       X       X       X       (sub address encoded in ia5)
+        */
+
+       int             x = 0;
+       int     p = 0;
+       int     len = 0;
+       char    tmp[2];
+       int     flag = 0;
+       int     odd = 0;
+       uint8_t lower = 0x0;
+       uint8_t upper = 0x0;
+
+       /* initalize the second element of tmp to \0 so that atoi doesn't go to far */
+       tmp[1]='\0';
+
+       /* set octet 1 aka IE id */
+       p = 0;
+       switch(type) {
+       /**************************************************************************/
+       case SNG_CALLED:                                                /* called party sub address */
+               subAddrIE[p] = 0x71;
+               break;
+       /**************************************************************************/
+       case SNG_CALLING:                                               /* calling party sub address */
+               subAddrIE[p] = 0x6d;
+               break;
+       /**************************************************************************/
+       default:                                                                /* not good */
+               SS7_ERROR("Sub-Address type is invalid: %d\n", type);
+               return FTDM_FAIL;
+               break;
+       /**************************************************************************/
+       } /* switch(type) */
+
+       /* set the subAddrIE pointer octet 4 */
+       p = 3;
+
+       /* loop through all digits in subAddr and insert them into subAddrIE */
+       while (1) {
+
+               /* grab a character */
+               tmp[0] = subAddr[x];
+
+               /* confirm it is a hex digit */
+               while ((!isxdigit(tmp[0])) && (tmp[0] != '\0')) {
+                       /* move to the next character in subAddr */
+                       x++;
+                       tmp[0] = subAddr[x];
+               }
+
+               /* check if tmp is null or a digit */
+               if (tmp[0] != '\0') {
+                       /* push it into the lower nibble using strtol to allow a-f chars */
+                       lower = strtol(&tmp[0], (char **)NULL, 16);
+                       /* move to the next digit */
+                       x++;
+                       /* grab a digit from the ftdm digits */
+                       tmp[0] = subAddr[x];
+
+                       /* check if the digit is a hex digit and that is not null */
+                       while (!(isxdigit(tmp[0])) && (tmp[0] != '\0')) {
+                               x++;
+                               tmp[0] = subAddr[x];
+                       } /* while(!(isdigit(tmp))) */
+
+                       /* check if tmp is null or a digit */
+                       if (tmp[0] != '\0') {
+                               /* push the digit into the upper nibble using strtol to allow a-f chars */
+                               upper = (strtol(&tmp[0], (char **)NULL, 16)) << 4;
+                       } else {
+                               /* there is no upper ... fill in spare */
+                               upper = 0x00;
+                               /* throw the odd flag since we need to buffer */
+                               odd = 1;
+                               /* throw the end flag */
+                               flag = 1;
+                       } /* if (tmp != '\0') */
+               } else {
+                       /* keep the odd flag down */
+                       odd = 0;
+
+                       /* throw the flag */
+                       flag = 1;
+
+                       /* bounce out right away */
+                       break;
+               }
+
+               /* fill in the octet */
+               subAddrIE[p] = upper | lower;
+
+               /* increment address length counter */
+               len++;
+
+               /* if the flag is we're through all the digits */
+               if (flag) break;
+
+               /* increment the subAddrIE pointer */
+               p++;
+
+               /* move to the next character in subAddr */
+               x++;
+
+       } /* while (subAddr[x] != '\0') */
+
+       /* set octet 2 aka length of subaddr */
+       p = 1;
+       subAddrIE[p] = len + 1;
+
+       /* set octet 3 aka type and o/e */
+       p = 2;
+       subAddrIE[p] = 0xa0 | (odd << 3);
+
+
+       return FTDM_SUCCESS;
+}
 
 /******************************************************************************/
 /* For Emacs: