📄 sip_uri.c
字号:
/* $Id: sip_uri.c 1222 2007-04-29 06:30:58Z bennylp $ *//* * Copyright (C) 2003-2007 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( pjsip_param *param_list, const pj_str_t *name ){ pjsip_param *p = param_list->next; while (p != param_list) { if (pj_stricmp(&p->name, name)==0) return p; p = p->next; } return NULL;}PJ_DEF(const pjsip_param*) pjsip_param_cfind( const pjsip_param *param_list, const pj_str_t *name ){ const pjsip_param *p = param_list->next; while (p != param_list) { if (pj_stricmp_alnum(&p->name, name)==0) return p; p = p->next; } return NULL;}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 != src_list) { pjsip_param *new_param = pj_pool_alloc(pool, sizeof(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(pool, sizeof(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 == 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 };#ifdef __GNUC__# define HAPPY_FLAG (void*)#else# define HAPPY_FLAG#endifstatic 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);static pjsip_uri_vptr sip_url_vptr = { HAPPY_FLAG &pjsip_url_get_scheme, HAPPY_FLAG &pjsip_get_uri, HAPPY_FLAG &pjsip_url_print, HAPPY_FLAG &pjsip_url_compare, HAPPY_FLAG &pjsip_url_clone};static pjsip_uri_vptr sips_url_vptr = { HAPPY_FLAG &pjsips_url_get_scheme, HAPPY_FLAG &pjsip_get_uri, HAPPY_FLAG &pjsip_url_print, HAPPY_FLAG &pjsip_url_compare, HAPPY_FLAG &pjsip_url_clone};static pjsip_uri_vptr name_addr_vptr = { HAPPY_FLAG &pjsip_name_addr_get_scheme, HAPPY_FLAG &pjsip_name_addr_get_uri, HAPPY_FLAG &pjsip_name_addr_print, HAPPY_FLAG &pjsip_name_addr_compare, HAPPY_FLAG &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(pool, sizeof(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; *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, pjsip_USER_SPEC); if (url->passwd.slen) { *buf++ = ':'; copy_advance_escape(buf, url->passwd, pjsip_PASSWD_SPEC); } *buf++ = '@'; } /* Print host. */ pj_assert(url->host.slen != 0); copy_advance_check(buf, url->host); /* Only print port if it is explicitly specified. * Port is not allowed in To and From header. */ /* Unfortunately some UA requires us to send back the port * number exactly as it was sent. We don't remember whether an * UA has sent us port, so we'll just send the port indiscrimately */ //PJ_TODO(SHOULD_DISALLOW_URI_PORT_IN_FROM_TO_HEADER) if (url->port && context != PJSIP_URI_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, 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, 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) { copy_advance_pair_escape(buf, ";maddr=", 7, url->maddr_param, 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, &pjsip_PARAM_CHAR_SPEC, &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, &pjsip_HDR_CHAR_SPEC, &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 搑eserved
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -