[sr-dev] [kamailio/kamailio] Incorrect translation of tel: uri to sip: uri in tel2sip() (#1173)

Donald Carr notifications at github.com
Thu Jul 13 22:53:13 CEST 2017


@miconda, thanks, that is exactly what I have now, so, will submit it when I can. Below is the code that I wrote with a new function named "std_tel2sip()", as a preview I used most of the old procedure where possible, and tried to keep the same style.

I have been given a task with a short deadline, so, will not be able to work on this anymore right now. I will get back to it as soon as possible.

Don.

```
/*
 * Compare function to sort tel: uri options acording to standard
 * before inserting into sip: uri
 *
 * See "RFC 3261 SIP: Session Initiation Protocol June 2002"  
 *     19.1.6 Relating SIP URIs and tel URLs
 */
typedef struct
{
        char *name;
        char *value;
} tel_param_t;
#define MAX_TEL_PARAMS (10)

int compare_tel_options(const void *v1, const void *v2)
{
        tel_param_t *p1 = (tel_param_t *) v1;
        tel_param_t *p2 = (tel_param_t *) v2;

        if (0 == strcasecmp(p1->name, "isdn-subaddress"))
        {
                return -1;
        }
        else if (0 == strcasecmp(p2->name, "isdn-subaddress"))
        {
                return 1;
        }
        else if (0 == strcasecmp(p1->name, "post-dial"))
        {
                return -1;
        }
        else if (0 == strcasecmp(p2->name, "post-dial"))
        {
                return 1;
        }
        else
        {
                return strcasecmp(p1->name, p2->name);
        }
}

/*
 *   Remove visual separators from the phone number 
 *   Assume it has been validated as a number containing 
 *   ONLY leading '+', digits, and visual separators.
 */
static void remove_visual_separators_from_phone(char *p)
{
        char *p2;
        p2 = p;
        while (*p != '\0')
        {
                 /* Skip all visual separators */
                 while ((*p != '\0') && ((*p == '.') || (*p == '-') || (*p == '(') || (*p == ')')))
                 {
                         p++; 
                 }
                 *p2 = *p; /* Until the first visual separator, these both point to  the same place. */
                           /* but, more efficient to just do it than an if statement each time. */
                 /* If we arrived at a terminator in the inner loop, time to exit */
                 if (*p == '\0') return;
                 /* Now we increment both pointers. */
                 p++;
                 p2++;
        }
        *p2 = '\0';  /* Make sure that the string is terminated after the last valid digit. */
}

/*
 * Check if this is a phone number.
 *   Assume possible leading '+'
 *   Assume separators '.', '-', '(', or ')' could be present.
 */
static int is_number(const char *p)
{
        if (*p == '+') p++;
        while (*p != '\0')
        {
                 if ((!isdigit(*p)) && (*p != '.') && (*p != '-') && (*p != '(') && (*p != ')')) return 0;
                 p++;
        }
        return 1;
}

/*
 * Converts URI, if it is tel URI, to SIP URI.  Returns 1, if
 * conversion succeeded or if no conversion was needed, i.e., URI was not
 * tel URI.  Returns -1, if conversion failed.  Takes SIP URI hostpart from
 * second parameter and (if needed) writes the result to third parameter.
 * This one attempts to be standards compliant and sort tel: uri parameters
 * copied to the sip: uri in the manner defined in the standard. It also 
 * deletes the "phone-context" parameter if it is a domain, and, takes visual
 * separators from the "phone-context" parameter if it is a telephone number.
 */
int std_tel2sip(struct sip_msg* _msg, char* _uri, char* _hostpart, char* _res)
{
        str uri, hostpart, tel_uri, sip_uri;
        char *at;
        int i, j, in_tel_parameters = 0;
        pv_spec_t *res;
        pv_value_t res_val;

        /* get parameters */
        if (get_str_fparam(&uri, _msg, (fparam_t*)_uri) < 0) {
                LM_ERR("failed to get uri value\n");
        }
        if (get_str_fparam(&hostpart, _msg, (fparam_t*)_hostpart) < 0) {
                LM_ERR("failed to get hostpart value\n");
        }
        res = (pv_spec_t *)_res;

        /* check if anything needs to be done */
        if (uri.len < 4) return 1;
        if (strncasecmp(uri.s, "tel:", 4) != 0) return 1;

        /* reserve memory for clean tel uri */
        tel_uri.s = pkg_malloc(uri.len+1);
        if (tel_uri.s == 0) {
                LM_ERR("no more pkg memory\n");
                return -1;
        }

        /* Remove visual separators before converting to SIP URI. Don't remove
         * visual separators in TEL URI parameters (after the first ";") */
        for (i=0, j=0; i < uri.len; i++) {
                if (in_tel_parameters == 0) {
                        if (uri.s[i] == ';')
                                in_tel_parameters = 1;
                }
                if (in_tel_parameters == 0) {
                        if ((uri.s[i] != '-') && (uri.s[i] != '.') &&
                                        (uri.s[i] != '(') && (uri.s[i] != ')'))
                                tel_uri.s[j++] = tolower(uri.s[i]);
                } else {
                        tel_uri.s[j++] = tolower(uri.s[i]);
                }
        }
        tel_uri.s[j] = '\0';
        tel_uri.len = strlen(tel_uri.s);

        /*** Start Code to sort tel: params *******/
        tel_param_t params[MAX_TEL_PARAMS];
        char *tmp_ptr = tel_uri.s + 4; // skip tel:

        int n_tel_params = 0;
        for (int i=0; i < MAX_TEL_PARAMS; i++)
        {
           tmp_ptr = strchr(tmp_ptr, ';');
           if (tmp_ptr == NULL)
           {
             break;
           }
           *tmp_ptr = '\0';
           tmp_ptr++;
           n_tel_params++;
           params[i].name = tmp_ptr;
        }
        for (int i=0; i < n_tel_params; i++)
        {
          tmp_ptr = strchr(params[i].name, '=');
          if (tmp_ptr == NULL)
          {
            params[i].value = "";
          }
          else
          {
             *tmp_ptr = '\0';
             tmp_ptr++;
             params[i].value = tmp_ptr;
          }
          if ((0 == strcasecmp(params[i].name, "phone-context")) && (is_number(params[i].value)))
          {
            remove_visual_separators_from_phone(params[i].value);
          }
           
        }
        if (n_tel_params > 1)
        {
          qsort(&params[0], n_tel_params, sizeof(tel_param_t), compare_tel_options);
        }
        /*** End Code to sort tel: params ******/

        /* reserve memory for resulting sip uri */
        sip_uri.len = 4 + tel_uri.len - 4 + 1 + hostpart.len + 1 + 10;
        sip_uri.s = pkg_malloc(sip_uri.len+1);
        if (sip_uri.s == 0) {
                LM_ERR("no more pkg memory\n");
                pkg_free(tel_uri.s);
                return -1;
        }

        /* create resulting sip uri */
        at = sip_uri.s;
        append_str(at, "sip:", 4);
        /** Original code tel: parameters NOT sorted 
        append_str(at, tel_uri.s + 4, tel_uri.len - 4);
        *****/
        /***** Start Changed Code for sorted tel: parameters ****/
        append_str(at, tel_uri.s + 4, strlen(tel_uri.s + 4)); /* This string was terminated after the number */
        /** Now we need to insert sorted tel: parameters **/
        for (int i=0; i < n_tel_params; i++)
        {
          /* If the phone context is a domain, it has already been extracted and is in the "host part" */
          if ((0 != strcasecmp(params[i].name, "phone-context")) || (is_number(params[i].value)))
          {
            append_chr(at, ';');
            append_str(at, params[i].name, strlen(params[i].name));
            append_chr(at, '=');
            append_str(at, params[i].value, strlen(params[i].value));
          }
        }
        /***** End Changed Code for sort tel: parameters ****/
        append_chr(at, '@');
        append_str(at, hostpart.s, hostpart.len);
        append_chr(at, ';');
        append_str(at, "user=phone", 10);

        /* tel_uri is not needed anymore */
        pkg_free(tel_uri.s);

        /* set result pv value and write sip uri to result pv */
        res_val.rs = sip_uri;
        res_val.flags = PV_VAL_STR;
        if (res->setf(_msg, &res->pvp, (int)EQ_T, &res_val) != 0) {
                LM_ERR("failed to set result pvar\n");
                pkg_free(sip_uri.s);
                return -1;
        }

        /* free allocated pkg memory and return */
        pkg_free(sip_uri.s);
        return 1;
}
```


-- 
You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub:
https://github.com/kamailio/kamailio/issues/1173#issuecomment-315198949
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.kamailio.org/pipermail/sr-dev/attachments/20170713/5348dade/attachment-0001.html>


More information about the sr-dev mailing list