diff options
author | David M. Lee <dlee@digium.com> | 2013-01-07 14:24:28 -0600 |
---|---|---|
committer | David M. Lee <dlee@digium.com> | 2013-01-07 14:24:28 -0600 |
commit | f3ab456a17af1c89a6e3be4d20c5944853df1cb0 (patch) | |
tree | d00e1a332cd038a6d906a1ea0ac91e1a4458e617 /pjsip/src/pjsip/sip_uri.c |
Import pjproject-2.0.1
Diffstat (limited to 'pjsip/src/pjsip/sip_uri.c')
-rw-r--r-- | pjsip/src/pjsip/sip_uri.c | 729 |
1 files changed, 729 insertions, 0 deletions
diff --git a/pjsip/src/pjsip/sip_uri.c b/pjsip/src/pjsip/sip_uri.c new file mode 100644 index 0000000..fba163c --- /dev/null +++ b/pjsip/src/pjsip/sip_uri.c @@ -0,0 +1,729 @@ +/* $Id: sip_uri.c 3553 2011-05-05 06:14:19Z nanang $ */ +/* + * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) + * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include <pjsip/sip_uri.h> +#include <pjsip/sip_msg.h> +#include <pjsip/sip_parser.h> +#include <pjsip/print_util.h> +#include <pjsip/sip_errno.h> +#include <pjlib-util/string.h> +#include <pj/string.h> +#include <pj/pool.h> +#include <pj/assert.h> + +/* + * Generic parameter manipulation. + */ +PJ_DEF(pjsip_param*) pjsip_param_find( const pjsip_param *param_list, + const pj_str_t *name ) +{ + pjsip_param *p = (pjsip_param*)param_list->next; + while (p != param_list) { + if (pj_stricmp(&p->name, name)==0) + return p; + p = p->next; + } + return NULL; +} + +PJ_DEF(int) pjsip_param_cmp( const pjsip_param *param_list1, + const pjsip_param *param_list2, + pj_bool_t ig_nf) +{ + const pjsip_param *p1; + + if ((ig_nf & 1)==0 && pj_list_size(param_list1)!=pj_list_size(param_list2)) + return 1; + + p1 = param_list1->next; + while (p1 != param_list1) { + const pjsip_param *p2; + p2 = pjsip_param_find(param_list2, &p1->name); + if (p2 ) { + int rc = pj_stricmp(&p1->value, &p2->value); + if (rc != 0) + return rc; + } else if ((ig_nf & 1)==0) + return 1; + + p1 = p1->next; + } + + return 0; +} + +PJ_DEF(void) pjsip_param_clone( pj_pool_t *pool, pjsip_param *dst_list, + const pjsip_param *src_list) +{ + const pjsip_param *p = src_list->next; + + pj_list_init(dst_list); + while (p && p != src_list) { + pjsip_param *new_param = PJ_POOL_ALLOC_T(pool, pjsip_param); + pj_strdup(pool, &new_param->name, &p->name); + pj_strdup(pool, &new_param->value, &p->value); + pj_list_insert_before(dst_list, new_param); + p = p->next; + } +} + + +PJ_DEF(void) pjsip_param_shallow_clone( pj_pool_t *pool, + pjsip_param *dst_list, + const pjsip_param *src_list) +{ + const pjsip_param *p = src_list->next; + + pj_list_init(dst_list); + while (p != src_list) { + pjsip_param *new_param = PJ_POOL_ALLOC_T(pool, pjsip_param); + new_param->name = p->name; + new_param->value = p->value; + pj_list_insert_before(dst_list, new_param); + p = p->next; + } +} + +PJ_DEF(pj_ssize_t) pjsip_param_print_on( const pjsip_param *param_list, + char *buf, pj_size_t size, + const pj_cis_t *pname_spec, + const pj_cis_t *pvalue_spec, + int sep) +{ + const pjsip_param *p; + char *startbuf; + char *endbuf; + int printed; + + p = param_list->next; + if (p == NULL || p == param_list) + return 0; + + startbuf = buf; + endbuf = buf + size; + + PJ_UNUSED_ARG(pname_spec); + + do { + *buf++ = (char)sep; + copy_advance_escape(buf, p->name, (*pname_spec)); + if (p->value.slen) { + *buf++ = '='; + if (*p->value.ptr == '"') + copy_advance(buf, p->value); + else + copy_advance_escape(buf, p->value, (*pvalue_spec)); + } + p = p->next; + if (sep == '?') sep = '&'; + } while (p != param_list); + + return buf-startbuf; +} + + +/* + * URI stuffs + */ +#define IS_SIPS(url) ((url)->vptr==&sips_url_vptr) + +static const pj_str_t *pjsip_url_get_scheme( const pjsip_sip_uri* ); +static const pj_str_t *pjsips_url_get_scheme( const pjsip_sip_uri* ); +static const pj_str_t *pjsip_name_addr_get_scheme( const pjsip_name_addr * ); +static void *pjsip_get_uri( pjsip_uri *uri ); +static void *pjsip_name_addr_get_uri( pjsip_name_addr *name ); + +static pj_str_t sip_str = { "sip", 3 }; +static pj_str_t sips_str = { "sips", 4 }; + +static pjsip_name_addr* pjsip_name_addr_clone( pj_pool_t *pool, + const pjsip_name_addr *rhs); +static pj_ssize_t pjsip_name_addr_print(pjsip_uri_context_e context, + const pjsip_name_addr *name, + char *buf, pj_size_t size); +static int pjsip_name_addr_compare( pjsip_uri_context_e context, + const pjsip_name_addr *naddr1, + const pjsip_name_addr *naddr2); +static pj_ssize_t pjsip_url_print( pjsip_uri_context_e context, + const pjsip_sip_uri *url, + char *buf, pj_size_t size); +static int pjsip_url_compare( pjsip_uri_context_e context, + const pjsip_sip_uri *url1, + const pjsip_sip_uri *url2); +static pjsip_sip_uri* pjsip_url_clone(pj_pool_t *pool, + const pjsip_sip_uri *rhs); + +typedef const pj_str_t* (*P_GET_SCHEME)(const void*); +typedef void* (*P_GET_URI)(void*); +typedef pj_ssize_t (*P_PRINT_URI)(pjsip_uri_context_e,const void *, + char*,pj_size_t); +typedef int (*P_CMP_URI)(pjsip_uri_context_e, const void*, + const void*); +typedef void* (*P_CLONE)(pj_pool_t*, const void*); + + +static pjsip_uri_vptr sip_url_vptr = +{ + (P_GET_SCHEME) &pjsip_url_get_scheme, + (P_GET_URI) &pjsip_get_uri, + (P_PRINT_URI) &pjsip_url_print, + (P_CMP_URI) &pjsip_url_compare, + (P_CLONE) &pjsip_url_clone +}; + +static pjsip_uri_vptr sips_url_vptr = +{ + (P_GET_SCHEME) &pjsips_url_get_scheme, + (P_GET_URI) &pjsip_get_uri, + (P_PRINT_URI) &pjsip_url_print, + (P_CMP_URI) &pjsip_url_compare, + (P_CLONE) &pjsip_url_clone +}; + +static pjsip_uri_vptr name_addr_vptr = +{ + (P_GET_SCHEME) &pjsip_name_addr_get_scheme, + (P_GET_URI) &pjsip_name_addr_get_uri, + (P_PRINT_URI) &pjsip_name_addr_print, + (P_CMP_URI) &pjsip_name_addr_compare, + (P_CLONE) &pjsip_name_addr_clone +}; + +static const pj_str_t *pjsip_url_get_scheme(const pjsip_sip_uri *url) +{ + PJ_UNUSED_ARG(url); + return &sip_str; +} + +static const pj_str_t *pjsips_url_get_scheme(const pjsip_sip_uri *url) +{ + PJ_UNUSED_ARG(url); + return &sips_str; +} + +static void *pjsip_get_uri( pjsip_uri *uri ) +{ + return uri; +} + +static void *pjsip_name_addr_get_uri( pjsip_name_addr *name ) +{ + return pjsip_uri_get_uri(name->uri); +} + +PJ_DEF(void) pjsip_sip_uri_set_secure( pjsip_sip_uri *url, + pj_bool_t secure ) +{ + url->vptr = secure ? &sips_url_vptr : &sip_url_vptr; +} + +PJ_DEF(void) pjsip_sip_uri_init(pjsip_sip_uri *url, pj_bool_t secure) +{ + pj_bzero(url, sizeof(*url)); + url->ttl_param = -1; + pjsip_sip_uri_set_secure(url, secure); + pj_list_init(&url->other_param); + pj_list_init(&url->header_param); +} + +PJ_DEF(pjsip_sip_uri*) pjsip_sip_uri_create( pj_pool_t *pool, + pj_bool_t secure ) +{ + pjsip_sip_uri *url = PJ_POOL_ALLOC_T(pool, pjsip_sip_uri); + pjsip_sip_uri_init(url, secure); + return url; +} + +static pj_ssize_t pjsip_url_print( pjsip_uri_context_e context, + const pjsip_sip_uri *url, + char *buf, pj_size_t size) +{ + int printed; + char *startbuf = buf; + char *endbuf = buf+size; + const pj_str_t *scheme; + const pjsip_parser_const_t *pc = pjsip_parser_const(); + + *buf = '\0'; + + /* Print scheme ("sip:" or "sips:") */ + scheme = pjsip_uri_get_scheme(url); + copy_advance_check(buf, *scheme); + *buf++ = ':'; + + /* Print "user:password@", if any. */ + if (url->user.slen) { + copy_advance_escape(buf, url->user, pc->pjsip_USER_SPEC); + if (url->passwd.slen) { + *buf++ = ':'; + copy_advance_escape(buf, url->passwd, pc->pjsip_PASSWD_SPEC); + } + + *buf++ = '@'; + } + + /* Print host. */ + pj_assert(url->host.slen != 0); + /* Detect IPv6 IP address */ + if (pj_memchr(url->host.ptr, ':', url->host.slen)) { + copy_advance_pair_quote_cond(buf, "", 0, url->host, '[', ']'); + } else { + copy_advance_check(buf, url->host); + } + + /* Only print port if it is explicitly specified. + * Port is not allowed in To and From header, see Table 1 in + * RFC 3261 Section 19.1.1 + */ + /* Note: ticket #1141 adds run-time setting to allow port number to + * appear in From/To header. Default is still false. + */ + if (url->port && + (context != PJSIP_URI_IN_FROMTO_HDR || + pjsip_cfg()->endpt.allow_port_in_fromto_hdr)) + { + if (endbuf - buf < 10) + return -1; + + *buf++ = ':'; + printed = pj_utoa(url->port, buf); + buf += printed; + } + + /* User param is allowed in all contexes */ + copy_advance_pair_check(buf, ";user=", 6, url->user_param); + + /* Method param is only allowed in external/other context. */ + if (context == PJSIP_URI_IN_OTHER) { + copy_advance_pair_escape(buf, ";method=", 8, url->method_param, + pc->pjsip_PARAM_CHAR_SPEC); + } + + /* Transport is not allowed in From/To header. */ + if (context != PJSIP_URI_IN_FROMTO_HDR) { + copy_advance_pair_escape(buf, ";transport=", 11, url->transport_param, + pc->pjsip_PARAM_CHAR_SPEC); + } + + /* TTL param is not allowed in From, To, Route, and Record-Route header. */ + if (url->ttl_param >= 0 && context != PJSIP_URI_IN_FROMTO_HDR && + context != PJSIP_URI_IN_ROUTING_HDR) + { + if (endbuf - buf < 15) + return -1; + pj_memcpy(buf, ";ttl=", 5); + printed = pj_utoa(url->ttl_param, buf+5); + buf += printed + 5; + } + + /* maddr param is not allowed in From and To header. */ + if (context != PJSIP_URI_IN_FROMTO_HDR && url->maddr_param.slen) { + /* Detect IPv6 IP address */ + if (pj_memchr(url->maddr_param.ptr, ':', url->maddr_param.slen)) { + copy_advance_pair_quote_cond(buf, ";maddr=", 7, url->maddr_param, + '[', ']'); + } else { + copy_advance_pair_escape(buf, ";maddr=", 7, url->maddr_param, + pc->pjsip_PARAM_CHAR_SPEC); + } + } + + /* lr param is not allowed in From, To, and Contact header. */ + if (url->lr_param && context != PJSIP_URI_IN_FROMTO_HDR && + context != PJSIP_URI_IN_CONTACT_HDR) + { + pj_str_t lr = { ";lr", 3 }; + if (endbuf - buf < 3) + return -1; + copy_advance_check(buf, lr); + } + + /* Other param. */ + printed = pjsip_param_print_on(&url->other_param, buf, endbuf-buf, + &pc->pjsip_PARAM_CHAR_SPEC, + &pc->pjsip_PARAM_CHAR_SPEC, ';'); + if (printed < 0) + return -1; + buf += printed; + + /* Header param. + * Header param is only allowed in these contexts: + * - PJSIP_URI_IN_CONTACT_HDR + * - PJSIP_URI_IN_OTHER + */ + if (context == PJSIP_URI_IN_CONTACT_HDR || context == PJSIP_URI_IN_OTHER) { + printed = pjsip_param_print_on(&url->header_param, buf, endbuf-buf, + &pc->pjsip_HDR_CHAR_SPEC, + &pc->pjsip_HDR_CHAR_SPEC, '?'); + if (printed < 0) + return -1; + buf += printed; + } + + *buf = '\0'; + return buf-startbuf; +} + +static pj_status_t pjsip_url_compare( pjsip_uri_context_e context, + const pjsip_sip_uri *url1, + const pjsip_sip_uri *url2) +{ + const pjsip_param *p1; + + /* + * Compare two SIP URL's according to Section 19.1.4 of RFC 3261. + */ + + /* SIP and SIPS URI are never equivalent. + * Note: just compare the vptr to avoid string comparison. + * Pretty neat huh!! + */ + if (url1->vptr != url2->vptr) + return PJSIP_ECMPSCHEME; + + /* Comparison of the userinfo of SIP and SIPS URIs is case-sensitive. + * This includes userinfo containing passwords or formatted as + * telephone-subscribers. + */ + if (pj_strcmp(&url1->user, &url2->user) != 0) + return PJSIP_ECMPUSER; + if (pj_strcmp(&url1->passwd, &url2->passwd) != 0) + return PJSIP_ECMPPASSWD; + + /* Comparison of all other components of the URI is + * case-insensitive unless explicitly defined otherwise. + */ + + /* The ordering of parameters and header fields is not significant + * in comparing SIP and SIPS URIs. + */ + + /* Characters other than those in the reserved set (see RFC 2396 [5]) + * are equivalent to their encoding. + */ + + /* An IP address that is the result of a DNS lookup of a host name + * does not match that host name. + */ + if (pj_stricmp(&url1->host, &url2->host) != 0) + return PJSIP_ECMPHOST; + + /* A URI omitting any component with a default value will not match a URI + * explicitly containing that component with its default value. + * For instance, a URI omitting the optional port component will not match + * a URI explicitly declaring port 5060. + * The same is true for the transport-parameter, ttl-parameter, + * user-parameter, and method components. + */ + + /* Port is not allowed in To and From header. + */ + if (context != PJSIP_URI_IN_FROMTO_HDR) { + if (url1->port != url2->port) + return PJSIP_ECMPPORT; + } + /* Transport is not allowed in From/To header. */ + if (context != PJSIP_URI_IN_FROMTO_HDR) { + if (pj_stricmp(&url1->transport_param, &url2->transport_param) != 0) + return PJSIP_ECMPTRANSPORTPRM; + } + /* TTL param is not allowed in From, To, Route, and Record-Route header. */ + if (context != PJSIP_URI_IN_FROMTO_HDR && + context != PJSIP_URI_IN_ROUTING_HDR) + { + if (url1->ttl_param != url2->ttl_param) + return PJSIP_ECMPTTLPARAM; + } + /* User param is allowed in all contexes */ + if (pj_stricmp(&url1->user_param, &url2->user_param) != 0) + return PJSIP_ECMPUSERPARAM; + /* Method param is only allowed in external/other context. */ + if (context == PJSIP_URI_IN_OTHER) { + if (pj_stricmp(&url1->method_param, &url2->method_param) != 0) + return PJSIP_ECMPMETHODPARAM; + } + /* maddr param is not allowed in From and To header. */ + if (context != PJSIP_URI_IN_FROMTO_HDR) { + if (pj_stricmp(&url1->maddr_param, &url2->maddr_param) != 0) + return PJSIP_ECMPMADDRPARAM; + } + + /* lr parameter is ignored (?) */ + /* lr param is not allowed in From, To, and Contact header. */ + + + /* All other uri-parameters appearing in only one URI are ignored when + * comparing the URIs. + */ + if (pjsip_param_cmp(&url1->other_param, &url2->other_param, 1)!=0) + return PJSIP_ECMPOTHERPARAM; + + /* URI header components are never ignored. Any present header component + * MUST be present in both URIs and match for the URIs to match. + * The matching rules are defined for each header field in Section 20. + */ + p1 = url1->header_param.next; + while (p1 != &url1->header_param) { + const pjsip_param *p2; + p2 = pjsip_param_find(&url2->header_param, &p1->name); + if (p2) { + /* It seems too much to compare two header params according to + * the rule of each header. We'll just compare them string to + * string.. + */ + if (pj_stricmp(&p1->value, &p2->value) != 0) + return PJSIP_ECMPHEADERPARAM; + } else { + return PJSIP_ECMPHEADERPARAM; + } + p1 = p1->next; + } + + /* Equal!! Pheuww.. */ + return PJ_SUCCESS; +} + + +PJ_DEF(void) pjsip_sip_uri_assign(pj_pool_t *pool, pjsip_sip_uri *url, + const pjsip_sip_uri *rhs) +{ + pj_strdup( pool, &url->user, &rhs->user); + pj_strdup( pool, &url->passwd, &rhs->passwd); + pj_strdup( pool, &url->host, &rhs->host); + url->port = rhs->port; + pj_strdup( pool, &url->user_param, &rhs->user_param); + pj_strdup( pool, &url->method_param, &rhs->method_param); + pj_strdup( pool, &url->transport_param, &rhs->transport_param); + url->ttl_param = rhs->ttl_param; + pj_strdup( pool, &url->maddr_param, &rhs->maddr_param); + pjsip_param_clone(pool, &url->other_param, &rhs->other_param); + pjsip_param_clone(pool, &url->header_param, &rhs->header_param); + url->lr_param = rhs->lr_param; +} + +static pjsip_sip_uri* pjsip_url_clone(pj_pool_t *pool, const pjsip_sip_uri *rhs) +{ + pjsip_sip_uri *url = PJ_POOL_ALLOC_T(pool, pjsip_sip_uri); + if (!url) + return NULL; + + pjsip_sip_uri_init(url, IS_SIPS(rhs)); + pjsip_sip_uri_assign(pool, url, rhs); + return url; +} + +static const pj_str_t *pjsip_name_addr_get_scheme(const pjsip_name_addr *name) +{ + pj_assert(name->uri != NULL); + return pjsip_uri_get_scheme(name->uri); +} + +PJ_DEF(void) pjsip_name_addr_init(pjsip_name_addr *name) +{ + name->vptr = &name_addr_vptr; + name->uri = NULL; + name->display.slen = 0; + name->display.ptr = NULL; +} + +PJ_DEF(pjsip_name_addr*) pjsip_name_addr_create(pj_pool_t *pool) +{ + pjsip_name_addr *name_addr = PJ_POOL_ALLOC_T(pool, pjsip_name_addr); + pjsip_name_addr_init(name_addr); + return name_addr; +} + +static pj_ssize_t pjsip_name_addr_print(pjsip_uri_context_e context, + const pjsip_name_addr *name, + char *buf, pj_size_t size) +{ + int printed; + char *startbuf = buf; + char *endbuf = buf + size; + pjsip_uri *uri; + + uri = (pjsip_uri*) pjsip_uri_get_uri(name->uri); + pj_assert(uri != NULL); + + if (context != PJSIP_URI_IN_REQ_URI) { + if (name->display.slen) { + if (endbuf-buf < 8) return -1; + *buf++ = '"'; + copy_advance(buf, name->display); + *buf++ = '"'; + *buf++ = ' '; + } + *buf++ = '<'; + } + + printed = pjsip_uri_print(context,uri, buf, size-(buf-startbuf)); + if (printed < 1) + return -1; + buf += printed; + + if (context != PJSIP_URI_IN_REQ_URI) { + *buf++ = '>'; + } + + *buf = '\0'; + return buf-startbuf; +} + +PJ_DEF(void) pjsip_name_addr_assign(pj_pool_t *pool, pjsip_name_addr *dst, + const pjsip_name_addr *src) +{ + pj_strdup( pool, &dst->display, &src->display); + dst->uri = (pjsip_uri*) pjsip_uri_clone(pool, src->uri); +} + +static pjsip_name_addr* pjsip_name_addr_clone( pj_pool_t *pool, + const pjsip_name_addr *rhs) +{ + pjsip_name_addr *addr = PJ_POOL_ALLOC_T(pool, pjsip_name_addr); + if (!addr) + return NULL; + + pjsip_name_addr_init(addr); + pjsip_name_addr_assign(pool, addr, rhs); + return addr; +} + +static int pjsip_name_addr_compare( pjsip_uri_context_e context, + const pjsip_name_addr *naddr1, + const pjsip_name_addr *naddr2) +{ + int d; + + /* Check that naddr2 is also a name_addr */ + if (naddr1->vptr != naddr2->vptr) + return -1; + + /* I'm not sure whether display name is included in the comparison. */ + if (pj_strcmp(&naddr1->display, &naddr2->display) != 0) { + return -1; + } + + pj_assert( naddr1->uri != NULL ); + pj_assert( naddr2->uri != NULL ); + + /* Compare name-addr as URL */ + d = pjsip_uri_cmp( context, naddr1->uri, naddr2->uri); + if (d) + return d; + + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// + +static const pj_str_t *other_uri_get_scheme( const pjsip_other_uri*); +static void *other_uri_get_uri( pjsip_other_uri*); +static pj_ssize_t other_uri_print( pjsip_uri_context_e context, + const pjsip_other_uri *url, + char *buf, pj_size_t size); +static int other_uri_cmp( pjsip_uri_context_e context, + const pjsip_other_uri *url1, + const pjsip_other_uri *url2); +static pjsip_other_uri* other_uri_clone( pj_pool_t *pool, + const pjsip_other_uri *rhs); + +static pjsip_uri_vptr other_uri_vptr = +{ + (P_GET_SCHEME) &other_uri_get_scheme, + (P_GET_URI) &other_uri_get_uri, + (P_PRINT_URI) &other_uri_print, + (P_CMP_URI) &other_uri_cmp, + (P_CLONE) &other_uri_clone +}; + + +PJ_DEF(pjsip_other_uri*) pjsip_other_uri_create(pj_pool_t *pool) +{ + pjsip_other_uri *uri = PJ_POOL_ZALLOC_T(pool, pjsip_other_uri); + uri->vptr = &other_uri_vptr; + return uri; +} + +static const pj_str_t *other_uri_get_scheme( const pjsip_other_uri *uri ) +{ + return &uri->scheme; +} + +static void *other_uri_get_uri( pjsip_other_uri *uri ) +{ + return uri; +} + +static pj_ssize_t other_uri_print(pjsip_uri_context_e context, + const pjsip_other_uri *uri, + char *buf, pj_size_t size) +{ + char *startbuf = buf; + char *endbuf = buf + size; + + PJ_UNUSED_ARG(context); + + if (uri->scheme.slen + uri->content.slen + 1 > (int)size) + return -1; + + /* Print scheme. */ + copy_advance(buf, uri->scheme); + *buf++ = ':'; + + /* Print content. */ + copy_advance(buf, uri->content); + + return (buf - startbuf); +} + +static int other_uri_cmp(pjsip_uri_context_e context, + const pjsip_other_uri *uri1, + const pjsip_other_uri *uri2) +{ + PJ_UNUSED_ARG(context); + + /* Check that uri2 is also an other_uri */ + if (uri1->vptr != uri2->vptr) + return -1; + + /* Scheme must match. */ + if (pj_stricmp(&uri1->scheme, &uri2->scheme) != 0) { + return PJSIP_ECMPSCHEME; + } + + /* Content must match. */ + if(pj_stricmp(&uri1->content, &uri2->content) != 0) { + return -1; + } + + /* Equal. */ + return 0; +} + +/* Clone *: URI */ +static pjsip_other_uri* other_uri_clone(pj_pool_t *pool, + const pjsip_other_uri *rhs) +{ + pjsip_other_uri *uri = pjsip_other_uri_create(pool); + pj_strdup(pool, &uri->scheme, &rhs->scheme); + pj_strdup(pool, &uri->content, &rhs->content); + + return uri; +} + |