⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sip_tel_uri.c

📁 基于sip协议的网络电话源码
💻 C
字号:
/* $Id: sip_tel_uri.c 974 2007-02-19 01:13:53Z 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_tel_uri.h>#include <pjsip/sip_msg.h>#include <pjsip/sip_parser.h>#include <pjsip/print_util.h>#include <pj/pool.h>#include <pj/assert.h>#include <pj/string.h>#include <pj/ctype.h>#include <pj/except.h>#include <pjlib-util/string.h>#include <pjlib-util/scanner.h>#define ALPHA#define DIGITS		    "0123456789"#define HEX		    "aAbBcCdDeEfF"#define HEX_DIGITS	    DIGITS HEX#define VISUAL_SEP	    "-.()"#define PHONE_DIGITS	    DIGITS VISUAL_SEP#define GLOBAL_DIGITS	    "+" PHONE_DIGITS#define LOCAL_DIGITS	    HEX_DIGITS "*#" VISUAL_SEP#define NUMBER_SPEC	    LOCAL_DIGITS GLOBAL_DIGITS#define PHONE_CONTEXT	    ALPHA GLOBAL_DIGITS//#define RESERVED	    ";/?:@&=+$,"#define RESERVED	    "/:@&$,+"#define MARK		    "-_.!~*'()"#define UNRESERVED	    ALPHA DIGITS MARK#define ESCAPED		    "%"#define URIC		    RESERVED UNRESERVED ESCAPED "[]+"#define PARAM_UNRESERVED    "[]/:&+$"#define PARAM_CHAR	    PARAM_UNRESERVED UNRESERVED ESCAPEDstatic pj_cis_buf_t cis_buf;static pj_cis_t pjsip_TEL_NUMBER_SPEC;static pj_cis_t pjsip_TEL_EXT_VALUE_SPEC;static pj_cis_t pjsip_TEL_PHONE_CONTEXT_SPEC;static pj_cis_t pjsip_TEL_URIC_SPEC;static pj_cis_t pjsip_TEL_VISUAL_SEP_SPEC;static pj_cis_t pjsip_TEL_PNAME_SPEC;static pj_cis_t pjsip_TEL_PVALUE_SPEC;static pj_cis_t pjsip_TEL_PVALUE_SPEC_ESC;static pj_cis_t pjsip_TEL_PARSING_PVALUE_SPEC;static pj_cis_t pjsip_TEL_PARSING_PVALUE_SPEC_ESC;static pj_str_t pjsip_ISUB_STR = { "isub", 4 };static pj_str_t pjsip_EXT_STR = { "ext", 3 };static pj_str_t pjsip_PH_CTX_STR = { "phone-context", 13 };static const pj_str_t *tel_uri_get_scheme( const pjsip_tel_uri* );static void *tel_uri_get_uri( pjsip_tel_uri* );static pj_ssize_t tel_uri_print( pjsip_uri_context_e context,				 const pjsip_tel_uri *url, 				 char *buf, pj_size_t size);static int tel_uri_cmp( pjsip_uri_context_e context,			const pjsip_tel_uri *url1, const pjsip_tel_uri *url2);static pjsip_tel_uri* tel_uri_clone(pj_pool_t *pool, const pjsip_tel_uri *rhs);static void*	      tel_uri_parse( pj_scanner *scanner, pj_pool_t *pool,				     pj_bool_t parse_params);#ifdef __GNUC__#  define HAPPY_FLAG	(void*)#else#  define HAPPY_FLAG#endifstatic pjsip_uri_vptr tel_uri_vptr = {    HAPPY_FLAG &tel_uri_get_scheme,    HAPPY_FLAG &tel_uri_get_uri,    HAPPY_FLAG &tel_uri_print,    HAPPY_FLAG &tel_uri_cmp,    HAPPY_FLAG &tel_uri_clone};PJ_DEF(pjsip_tel_uri*) pjsip_tel_uri_create(pj_pool_t *pool){    pjsip_tel_uri *uri = pj_pool_zalloc(pool, sizeof(pjsip_tel_uri));    uri->vptr = &tel_uri_vptr;    pj_list_init(&uri->other_param);    return uri;}static const pj_str_t *tel_uri_get_scheme( const pjsip_tel_uri *uri ){    PJ_UNUSED_ARG(uri);    return &pjsip_TEL_STR;}static void *tel_uri_get_uri( pjsip_tel_uri *uri ){    return uri;}pj_status_t pjsip_tel_uri_subsys_init(void){    pj_status_t status;    pj_cis_buf_init(&cis_buf);    status = pj_cis_init(&cis_buf, &pjsip_TEL_EXT_VALUE_SPEC);    PJ_ASSERT_RETURN(status==PJ_SUCCESS, status);    pj_cis_add_str(&pjsip_TEL_EXT_VALUE_SPEC, PHONE_DIGITS);    status = pj_cis_init(&cis_buf, &pjsip_TEL_NUMBER_SPEC);    PJ_ASSERT_RETURN(status==PJ_SUCCESS, status);    pj_cis_add_str(&pjsip_TEL_NUMBER_SPEC, NUMBER_SPEC);    status = pj_cis_init(&cis_buf, &pjsip_TEL_VISUAL_SEP_SPEC);    PJ_ASSERT_RETURN(status==PJ_SUCCESS, status);    pj_cis_add_str(&pjsip_TEL_VISUAL_SEP_SPEC, VISUAL_SEP);    status = pj_cis_init(&cis_buf, &pjsip_TEL_PHONE_CONTEXT_SPEC);    PJ_ASSERT_RETURN(status==PJ_SUCCESS, status);    pj_cis_add_alpha(&pjsip_TEL_PHONE_CONTEXT_SPEC);    pj_cis_add_num(&pjsip_TEL_PHONE_CONTEXT_SPEC);    pj_cis_add_str(&pjsip_TEL_PHONE_CONTEXT_SPEC, PHONE_CONTEXT);    status = pj_cis_init(&cis_buf, &pjsip_TEL_URIC_SPEC);    PJ_ASSERT_RETURN(status==PJ_SUCCESS, status);    pj_cis_add_alpha(&pjsip_TEL_URIC_SPEC);    pj_cis_add_num(&pjsip_TEL_URIC_SPEC);    pj_cis_add_str(&pjsip_TEL_URIC_SPEC, URIC);    status = pj_cis_init(&cis_buf, &pjsip_TEL_PNAME_SPEC);    PJ_ASSERT_RETURN(status==PJ_SUCCESS, status);    pj_cis_add_alpha(&pjsip_TEL_PNAME_SPEC);    pj_cis_add_num(&pjsip_TEL_PNAME_SPEC);    pj_cis_add_str(&pjsip_TEL_PNAME_SPEC, "-");    status = pj_cis_init(&cis_buf, &pjsip_TEL_PVALUE_SPEC);    PJ_ASSERT_RETURN(status==PJ_SUCCESS, status);    pj_cis_add_alpha(&pjsip_TEL_PVALUE_SPEC);    pj_cis_add_num(&pjsip_TEL_PVALUE_SPEC);    pj_cis_add_str(&pjsip_TEL_PVALUE_SPEC, PARAM_CHAR);    status = pj_cis_dup(&pjsip_TEL_PVALUE_SPEC_ESC, &pjsip_TEL_PVALUE_SPEC);    pj_cis_del_str(&pjsip_TEL_PVALUE_SPEC_ESC, "%");    status = pj_cis_dup(&pjsip_TEL_PARSING_PVALUE_SPEC, &pjsip_TEL_URIC_SPEC);    PJ_ASSERT_RETURN(status==PJ_SUCCESS, status);    pj_cis_add_cis(&pjsip_TEL_PARSING_PVALUE_SPEC, &pjsip_TEL_PVALUE_SPEC);    pj_cis_add_str(&pjsip_TEL_PARSING_PVALUE_SPEC, "=");    status = pj_cis_dup(&pjsip_TEL_PARSING_PVALUE_SPEC_ESC, 			&pjsip_TEL_PARSING_PVALUE_SPEC);    pj_cis_del_str(&pjsip_TEL_PARSING_PVALUE_SPEC_ESC, "%");    status = pjsip_register_uri_parser("tel", &tel_uri_parse);    PJ_ASSERT_RETURN(status==PJ_SUCCESS, status);    return PJ_SUCCESS;}/* Print tel: URI */static pj_ssize_t tel_uri_print( pjsip_uri_context_e context,				 const pjsip_tel_uri *uri, 				 char *buf, pj_size_t size){    int printed;    char *startbuf = buf;    char *endbuf = buf+size;    PJ_UNUSED_ARG(context);    /* Print scheme. */    copy_advance(buf, pjsip_TEL_STR);    *buf++ = ':';    /* Print number. */    copy_advance_escape(buf, uri->number, pjsip_TEL_NUMBER_SPEC);    /* ISDN sub-address or extension must appear first. */    /* Extension param. */    copy_advance_pair_escape(buf, ";ext=", 5, uri->ext_param, 			     pjsip_TEL_EXT_VALUE_SPEC);    /* ISDN sub-address. */    copy_advance_pair_escape(buf, ";isub=", 6, uri->isub_param, 			     pjsip_TEL_URIC_SPEC);    /* Followed by phone context, if present. */    copy_advance_pair_escape(buf, ";phone-context=", 15, uri->context, 			     pjsip_TEL_PHONE_CONTEXT_SPEC);    /* Print other parameters. */    printed = pjsip_param_print_on(&uri->other_param, buf, (endbuf-buf), 				   &pjsip_TEL_PNAME_SPEC, 				   &pjsip_TEL_PVALUE_SPEC, ';');    if (printed < 0)	return -1;    buf += printed;    return (buf-startbuf);}/* Compare two numbers, according to RFC 3966: *  - both must be either local or global numbers. *  - The 'global-number-digits' and the 'local-number-digits' must be *    equal, after removing all visual separators. */PJ_DEF(int) pjsip_tel_nb_cmp(const pj_str_t *number1, const pj_str_t *number2){    const char *s1 = number1->ptr,	       *e1 = number1->ptr + number1->slen,	       *s2 = number2->ptr,	       *e2 = number2->ptr + number2->slen;    /* Compare each number, ignoreing visual separators. */    while (s1!=e1 && s2!=e2) {	int diff;	if (pj_cis_match(&pjsip_TEL_VISUAL_SEP_SPEC, *s1)) {	    ++s1;	    continue;	}	if (pj_cis_match(&pjsip_TEL_VISUAL_SEP_SPEC, *s2)) {	    ++s2;	    continue;	}	diff = pj_tolower(*s1) - pj_tolower(*s2);	if (!diff) {	    ++s1, ++s2;	    continue;	} else	    return diff;    }    /* Exhaust remaining visual separators. */    while (s1!=e1 && pj_cis_match(&pjsip_TEL_VISUAL_SEP_SPEC, *s1))	++s1;    while (s2!=e2 && pj_cis_match(&pjsip_TEL_VISUAL_SEP_SPEC, *s2))	++s2;    if (s1==e1 && s2==e2)	return 0;    else if (s1==e1)	return -1;    else	return 1;}/* Compare two tel: URI */static int tel_uri_cmp( pjsip_uri_context_e context,			const pjsip_tel_uri *url1, const pjsip_tel_uri *url2){    int result;    PJ_UNUSED_ARG(context);    /* Scheme must match. */    if (url1->vptr != url2->vptr)	return -1;    /* Compare number. */    result = pjsip_tel_nb_cmp(&url1->number, &url2->number);    if (result != 0)	return result;    /* Compare phone-context as hostname or as as global nb. */    if (url1->context.slen) {	if (*url1->context.ptr != '+')	    result = pj_stricmp(&url1->context, &url2->context);	else	    result = pjsip_tel_nb_cmp(&url1->context, &url2->context);	if (result != 0)	    return result;    } else if (url2->context.slen)	return -1;    /* Compare extension. */    if (url1->ext_param.slen) {	result = pjsip_tel_nb_cmp(&url1->ext_param, &url2->ext_param);	if (result != 0)	    return result;    }    /* Compare isub bytes by bytes. */    if (url1->isub_param.slen) {	result = pj_stricmp(&url1->isub_param, &url2->isub_param);	if (result != 0)	    return result;    }    /* Other parameters are compared regardless of the order.     * If one URI has parameter not found in the other URI, the URIs are     * not equal.     */    if (url1->other_param.next != &url1->other_param) {	const pjsip_param *p1, *p2;	int cnt1 = 0, cnt2 = 0;	p1 = url1->other_param.next;	while (p1 != &url1->other_param) {	    p2 = pjsip_param_cfind(&url2->other_param, &p1->name);	    if (!p2 )		return 1;	    result = pj_stricmp(&p1->value, &p2->value);	    if (result != 0)		return result;	    p1 = p1->next;	    ++cnt1;	}	p2 = url2->other_param.next;	while (p2 != &url2->other_param)	    ++cnt2, p2 = p2->next;	if (cnt1 < cnt2)	    return -1;	else if (cnt1 > cnt2)	    return 1;    } else if (url2->other_param.next != &url2->other_param)	return -1;    /* Equal. */    return 0;}/* Clone tel: URI */static pjsip_tel_uri* tel_uri_clone(pj_pool_t *pool, const pjsip_tel_uri *rhs){    pjsip_tel_uri *uri = pjsip_tel_uri_create(pool);    pj_strdup(pool, &uri->number, &rhs->number);    pj_strdup(pool, &uri->context, &rhs->context);    pj_strdup(pool, &uri->ext_param, &rhs->ext_param);    pj_strdup(pool, &uri->isub_param, &rhs->isub_param);    pjsip_param_clone(pool, &uri->other_param, &rhs->other_param);    return uri;}/* Parse tel: URI  * THis actually returns (pjsip_tel_uri *) type. */static void* tel_uri_parse( pj_scanner *scanner, pj_pool_t *pool,			    pj_bool_t parse_params){    pjsip_tel_uri *uri;    pj_str_t token;    int skip_ws = scanner->skip_ws;    scanner->skip_ws = 0;    /* Parse scheme. */    pj_scan_get(scanner, &pjsip_TOKEN_SPEC, &token);    if (pj_scan_get_char(scanner) != ':')	PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);    if (pj_stricmp_alnum(&token, &pjsip_TEL_STR) != 0)	PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);    /* Create URI */    uri = pjsip_tel_uri_create(pool);    /* Get the phone number. */#if defined(PJSIP_UNESCAPE_IN_PLACE) && PJSIP_UNESCAPE_IN_PLACE!=0    pj_scan_get_unescape(scanner, &pjsip_TEL_NUMBER_SPEC, &uri->number);#else    pj_scan_get(scanner, &pjsip_TEL_NUMBER_SPEC, &uri->number);    uri->number = pj_str_unescape(pool, &uri->number);#endif    /* Get all parameters. */    if (parse_params && *scanner->curptr==';') {	pj_str_t pname, pvalue;	do {	    /* Eat the ';' separator. */	    pj_scan_get_char(scanner);	    /* Get pname. */	    pj_scan_get(scanner, &pjsip_PARAM_CHAR_SPEC, &pname);	    if (*scanner->curptr == '=') {		pj_scan_get_char(scanner);#		if defined(PJSIP_UNESCAPE_IN_PLACE) && PJSIP_UNESCAPE_IN_PLACE!=0		    pj_scan_get_unescape( scanner, 					  &pjsip_TEL_PARSING_PVALUE_SPEC_ESC,					  &pvalue);#		else		    pj_scan_get(scanner, &pjsip_TEL_PARSING_PVALUE_SPEC, 				&pvalue);		    pvalue = pj_str_unescape(pool, &pvalue);#		endif	    } else {		pvalue.slen = 0;		pvalue.ptr = NULL;	    }	    /* Save the parameters. */	    if (pj_stricmp_alnum(&pname, &pjsip_ISUB_STR)==0) {		uri->isub_param = pvalue;	    } else if (pj_stricmp_alnum(&pname, &pjsip_EXT_STR)==0) {		uri->ext_param = pvalue;	    } else if (pj_stricmp_alnum(&pname, &pjsip_PH_CTX_STR)==0) {		uri->context = pvalue;	    } else {		pjsip_param *param = pj_pool_alloc(pool, sizeof(pjsip_param));		param->name = pname;		param->value = pvalue;		pj_list_insert_before(&uri->other_param, param);	    }	} while (*scanner->curptr==';');    }    scanner->skip_ws = skip_ws;    return uri;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -