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

📄 sip_parse_uri.c

📁 VoIP use SIP protocol interface
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END *//* * Copyright 2006 Sun Microsystems, Inc.  All rights reserved. * Use is subject to license terms. */#pragma ident	"@(#)sip_parse_uri.c	1.3	06/08/16 SMI"#include <stdlib.h>#include <string.h>#include <ctype.h>#include "sip_parse_uri.h"/* * SIP-URI          =  "sip:" [ userinfo ] hostport uri-parameters [ headers ] * SIPS-URI         =  "sips:" [ userinfo ] hostport uri-parameters [ headers ] * userinfo         =  ( user / telephone-subscriber ) [ ":" password ] "@" * user             =  1*( unreserved / escaped / user-unreserved ) * user-unreserved  =  "&" / "=" / "+" / "$" / "," / ";" / "?" / "/" * password         =  *( unreserved / escaped / "&" / "=" / "+" / "$" / "," ) * hostport         =  host [ ":" port ] * host             =  hostname / IPv4address / IPv6reference * hostname         =  *( domainlabel "." ) toplabel [ "." ] * domainlabel      =  alphanum / alphanum *( alphanum / "-" ) alphanum * toplabel         =  ALPHA / ALPHA *( alphanum / "-" ) alphanum * IPv4address    =  1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT * IPv6reference  =  "[" IPv6address "]" * IPv6address    =  hexpart [ ":" IPv4address ] * hexpart        =  hexseq / hexseq "::" [ hexseq ] / "::" [ hexseq ] * hexseq         =  hex4 *( ":" hex4) * hex4           =  1*4HEXDIG * port           =  1*DIGIT * * The BNF for telephone-subscriber can be found in RFC 2806 [9].  Note, * however, that any characters allowed there that are not allowed in * the user part of the SIP URI MUST be escaped. * * uri-parameters    =  *( ";" uri-parameter) * uri-parameter     =  transport-param / user-param / method-param *                      / ttl-param / maddr-param / lr-param / other-param * transport-param   =  "transport="( "udp" / "tcp" / "sctp" / "tls" *                     / other-transport) * other-transport   =  token * user-param        =  "user=" ( "phone" / "ip" / other-user) * other-user        =  token * method-param      =  "method=" Method * ttl-param         =  "ttl=" ttl * maddr-param       =  "maddr=" host * lr-param          =  "lr" * other-param       =  pname [ "=" pvalue ] * pname             =  1*paramchar * pvalue            =  1*paramchar * paramchar         =  param-unreserved / unreserved / escaped * param-unreserved  =  "[" / "]" / "/" / ":" / "&" / "+" / "$" * headers         =  "?" header *( "&" header ) * header          =  hname "=" hvalue * hname           =  1*( hnv-unreserved / unreserved / escaped ) * hvalue          =  *( hnv-unreserved / unreserved / escaped ) * hnv-unreserved  =  "[" / "]" / "/" / "?" / ":" / "+" / "$" * */#define	SIP_URI_MSG_BUF_SZ	100#define	SIP_URI_ISHEX(c)					\	(((int)(c) >= 0x30 && (int)(c) <= 0x39) || 	\	((int)(c) >= 0x41 && (int)(c) <= 0x46) || 	\	((int)(c) >= 0x61 && (int)(c) <= 0x66))#define	SIP_URI_ISURLESCAPE(scan, end)			\	((scan) + 2 < (end) && (scan)[0] == '%' && 	\	SIP_URI_ISHEX((scan)[1]) && SIP_URI_ISHEX((scan[2])))/* * URL character classes *  mark	- _ . ! ~ * ' () *  reserved	; / ? : @ & = + $ ,    also [] for IPv6 *  unreserved	alphanum mark *  pchar	: @ & = + $ , unreserved *  userinfo	; : & = + $ , unreserved escaped *  relsegment	; @ & = + $ , unreserved escaped *  reg_name	; : @ & = + $ , unreserved escaped *  token	- _ . ! ~ * ' %  + ` *  param-unreserved  [ ] / : + $ & *  hnv-unreserved    [ ] / : + $ ? */#define	SIP_URI_ALPHA_BIT		0x0001#define	SIP_URI_DIGIT_BIT		0x0002#define	SIP_URI_ALNUM_BITS		0x0003#define	SIP_URI_SCHEME_BIT		0x0004	/* for - + . */#define	SIP_URI_TOKEN_BIT		0x0008	/* for - _ . ! ~ * ' % + ` */#define	SIP_URI_QUEST_BIT		0x0010	/* for ? */#define	SIP_URI_AT_BIT			0x0020	/* for @ */#define	SIP_URI_COLON_BIT		0x0040	/* for : */#define	SIP_URI_SEMI_BIT		0x0080	/* for ; */#define	SIP_URI_DASH_BIT		0x0100	/* for - */#define	SIP_URI_MARK_BIT		0x0200	/* for - _ . ! ~ * ' ( ) */#define	SIP_URI_AND_BIT			0x0400	/* for & */#define	SIP_URI_PHCOMM_BIT		0x0800	/* for [ ] / : + $ */#define	SIP_URI_OTHER_BIT		0x1000	/* for = + $ , */#define	SIP_URI_SLASH_BIT		0x2000	/* for / */#define	SIP_URI_VISUALSEP_BIT		0x4000	/* for -.() */#define	SIP_URI_DTMFURI_DIGIT_BIT	0x8000	/* for *ABCD */#define	a 			SIP_URI_ALPHA_BIT#define	d 			SIP_URI_DIGIT_BIT#define	s 			SIP_URI_SCHEME_BIT#define	t 			SIP_URI_TOKEN_BIT#define	q 			SIP_URI_QUEST_BIT#define	m 			SIP_URI_AT_BIT#define	c 			SIP_URI_COLON_BIT#define	i 			SIP_URI_SEMI_BIT#define	h 			SIP_URI_DASH_BIT#define	k 			SIP_URI_MARK_BIT#define	n 			SIP_URI_AND_BIT#define	o 			SIP_URI_PHCOMM_BIT#define	r 			SIP_URI_OTHER_BIT#define	l 			SIP_URI_SLASH_BIT#define	v 			SIP_URI_VISUALSEP_BIT#define	f 			SIP_URI_DTMFURI_DIGIT_BITstatic const unsigned short sip_uri_table[256] = {	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	t|k,	0,	0,	o|r,	t,	n,	t|k,	k|v,	k|v,	t|k|f, s|t|r|o,	r,  h|s|t|k|v, s|t|k|v,	o|l,	d,	d,	d,	d,	d,	d,	d,	d,	d,	d,	c|o,	i,	0,	r,	0,	q,	m,	a|f,	a|f,	a|f,	a|f,	a,	a,	a,	a,	a,	a,	a,	a,	a,	a,	a,	a,	a,	a,	a,	a,	a,	a,	a,	a,	a,	a,	o,	0,	o,	0,	t|k,	t,	a,	a,	a,	a,	a,	a,	a,	a,	a,	a,	a,	a,	a,	a,	a,	a,	a,	a,	a,	a,	a,	a,	a,	a,	a,	a,	0,	0,	0,	t|k,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,};#undef	a#undef	d#undef	s#undef	t#undef	q#undef	m#undef	c#undef	i#undef	h#undef	k#undef	n#undef	o#undef	r#undef	l#undef	v#undef	f#define	SIP_URI_UT(c)			sip_uri_table[(unsigned char)(c)]#define	SIP_URI_ISALPHA(c)		(SIP_URI_UT(c) & SIP_URI_ALPHA_BIT)#define	SIP_URI_ISDIGIT(c)		(SIP_URI_UT(c) & SIP_URI_DIGIT_BIT)#define	SIP_URI_ISALNUM(c)		(SIP_URI_UT(c) & SIP_URI_ALNUM_BITS)#define	SIP_URI_ISSCHEME(c)		\		(SIP_URI_UT(c) & (SIP_URI_ALNUM_BITS|SIP_URI_SCHEME_BIT))#define	SIP_URI_ISTOKEN(c)		\		(SIP_URI_UT(c) & (SIP_URI_ALNUM_BITS|SIP_URI_TOKEN_BIT))#define	SIP_URI_ISSIPDELIM(c)		\		(SIP_URI_UT(c) & (SIP_URI_SEMI_BIT|SIP_URI_QUEST_BIT))#define	SIP_URI_ISSIPHDELIM(c)					\	(SIP_URI_UT(c) & (SIP_URI_COLON_BIT|SIP_URI_SEMI_BIT|SIP_URI_QUEST_BIT))#define	SIP_URI_ISHOST(c)		\		(SIP_URI_UT(c) & (SIP_URI_ALNUM_BITS|SIP_URI_DASH_BIT))#define	SIP_URI_ISUSER(c)						\	(SIP_URI_UT(c) & (SIP_URI_OTHER_BIT|SIP_URI_SEMI_BIT|		\	SIP_URI_QUEST_BIT|SIP_URI_SLASH_BIT|SIP_URI_AND_BIT))#define	SIP_URI_ISABSHDELIM(c)					\	(SIP_URI_UT(c) & \	(SIP_URI_SLASH_BIT|SIP_URI_COLON_BIT|SIP_URI_QUEST_BIT))#define	SIP_URI_ISABSDELIM(c)	\	(SIP_URI_UT(c) & (SIP_URI_SLASH_BIT|SIP_URI_QUEST_BIT))#define	SIP_URI_ISUNRESERVED(c)	\	(SIP_URI_UT(c) & (SIP_URI_ALNUM_BITS|SIP_URI_MARK_BIT))#define	SIP_URI_ISPARAM(c)						\	(SIP_URI_UT(c) & (SIP_URI_PHCOMM_BIT|SIP_URI_AND_BIT|\	SIP_URI_ALNUM_BITS|SIP_URI_MARK_BIT))#define	SIP_URI_ISHEADER(c)						\	(SIP_URI_UT(c) & (SIP_URI_PHCOMM_BIT|SIP_URI_QUEST_BIT|\	SIP_URI_ALNUM_BITS|SIP_URI_MARK_BIT))#define	SIP_URI_ISOTHER(c)		(SIP_URI_UT(c) & SIP_URI_OTHER_BIT)#define	SIP_URI_ISRESERVED(c)					\	(SIP_URI_UT(c) & (SIP_URI_SEMI_BIT|SIP_URI_SLASH_BIT|	\	SIP_URI_QUEST_BIT| SIP_URI_COLON_BIT|SIP_URI_AT_BIT|	\	SIP_URI_AND_BIT|SIP_URI_OTHER_BIT))#define	SIP_URI_ISPCHAR(c)	\	(SIP_URI_UT(c) & (SIP_URI_COLON_BIT|SIP_URI_AT_BIT|	\	SIP_URI_AND_BIT|SIP_URI_OTHER_BIT))#define	SIP_URI_ISREGNAME(c)					\	(SIP_URI_UT(c) & 	\	(SIP_URI_OTHER_BIT|SIP_URI_SEMI_BIT|SIP_URI_COLON_BIT|	\	SIP_URI_AT_BIT|SIP_URI_AND_BIT))#define	SIP_URI_ISPHONEDIGIT(c)	\	(SIP_URI_UT(c) & (SIP_URI_DIGIT_BIT|SIP_URI_VISUALSEP_BIT))#define	SIP_URI_ISDTMFDIGIT(c)	(SIP_URI_UT(c) & SIP_URI_DTMFURI_DIGIT_BIT)/* static functions */static int  sip_uri_url_casecmp(const char *, const char *, unsigned);static void sip_uri_parse_params(_sip_uri_t *, char *, char *);static void sip_uri_parse_headers(_sip_uri_t *, char *, char *);static void sip_uri_parse_abs_opaque(_sip_uri_t *, char *, char *);static void sip_uri_parse_abs_query(_sip_uri_t *, char *, char *);static void sip_uri_parse_abs_path(_sip_uri_t *, char *, char *);static void sip_uri_parse_abs_regname(_sip_uri_t *, char *, char *);static int  sip_uri_parse_scheme(_sip_uri_t *, char *, char *);static void sip_uri_parse_password(_sip_uri_t *, char *, char *);static void sip_uri_parse_user(_sip_uri_t *, char *, char *);static void sip_uri_parse_port(_sip_uri_t *, char *, char *);static void sip_uri_parse_netpath(_sip_uri_t *, char **, char *, boolean_t);static int  sip_uri_parse_ipv6(char *, char *);static int  sip_uri_parse_ipv4(char *, char *);static int  sip_uri_parse_hostname(char *, char *);static int sip_uri_parse_tel(char *, char *);static int sip_uri_parse_tel_areaspe(char *, char *);static int sip_uri_parse_tel_servicepro(char *, char *);static int sip_uri_parse_tel_futureext(char *, char *);static int sip_uri_isTokenchar(char **, char *);static int sip_uri_isEscapedPound(char **, char *);static int sip_uri_hexVal(char *, char *);static int SIP_URI_HEXVAL(int);/* * get the hex value of a char */static intSIP_URI_HEXVAL(int c){	if (c >= 0x30 && c <= 0x39)		return (c - '0');	if (c >= 0x41 && c <= 0x46)		return (c - 'A' + 10);	if (c >= 0x61 && c <= 0x66)		return (c - 'a' + 10);	return (c);}/* * basic ASCII case-insensitive comparison */static intsip_uri_url_casecmp(const char *str1, const char *str2, unsigned len){	unsigned	j;	for (j = 0; j < len && tolower(str1[j]) == tolower(str2[j]) &&	    str1[j] != '\0'; ++j) {		;	}	return (j == len ? 0 : tolower(str2[j]) - tolower(str1[j]));}/* * telephone-subscriber  = global-phone-number / local-phone-number * Please refer to RFC 2806 */static intsip_uri_parse_tel(char *scan, char *uend){	char	*mark = (char *)0;	int	ret = 0;	int	isGlobal = 0;	int	quote = 0;	if (scan == uend)		return (0);	if (*scan == '+') {		++scan;		isGlobal = 1;	}	mark = scan;	if (isGlobal) {		while (scan < uend && SIP_URI_ISPHONEDIGIT(*scan))			++scan;	} else {		while (scan < uend &&		    (SIP_URI_ISPHONEDIGIT(*scan) ||		    SIP_URI_ISDTMFDIGIT(*scan) ||		    sip_uri_isEscapedPound(&scan, uend) ||		    *scan == 'p' || *scan == 'w')) {			++scan;		}	}	if (mark == scan || (scan < uend && *scan != ';'))		return (0);	/* parse isdn-subaddress */	if (uend - scan > 6 && !sip_uri_url_casecmp(scan, ";isub=", 6)) {		scan += 6;		mark = scan;		while (scan < uend && SIP_URI_ISPHONEDIGIT(*scan))			++scan;		if (mark == scan || (scan < uend && *scan != ';'))			return (0);	}	/* parse post-dial */	if (uend - scan > 7 && !sip_uri_url_casecmp(scan, ";postd=", 7)) {		scan += 7;		mark = scan;		while (scan < uend &&		    (SIP_URI_ISPHONEDIGIT(*scan) ||		    SIP_URI_ISDTMFDIGIT(*scan) ||		    sip_uri_isEscapedPound(&scan, uend) ||		    *scan == 'p' || *scan == 'w')) {			++scan;		}		if (mark == scan || (scan < uend && *scan != ';'))			return (0);	}	if (!isGlobal) {		/* parse area-specifier */		if (uend - scan > 15 &&		    !sip_uri_url_casecmp(scan, ";phone-context=", 15)) {			scan += 15;			mark = scan;			while (scan < uend && *scan != ';')				++scan;			ret = sip_uri_parse_tel_areaspe(mark, scan);		}	} else {		ret = 1;	}	/* parse area-specifier, service-provider, future-extension */	while (scan < uend && ret) {		if (uend - scan > 15 &&			!sip_uri_url_casecmp(scan, ";phone-context=", 15)) {			scan += 15;			mark = scan;			while (scan < uend && *scan != ';')				++scan;			ret = sip_uri_parse_tel_areaspe(mark, scan);		} else if (uend - scan > 5 &&		    !sip_uri_url_casecmp(scan, ";tsp=", 5)) {			scan += 5;			mark = scan;			while (scan < uend && *scan != ';')				++scan;			ret = sip_uri_parse_tel_servicepro(mark, scan);		} else {			++scan;			mark = scan;			while (scan < uend && (*scan != ';' || quote)) {				if (sip_uri_hexVal(scan, uend) == 0x22) {					quote = !quote;					scan += 3;				} else {					++scan;				}			}			ret = sip_uri_parse_tel_futureext(mark, scan);		}	}	return (ret && scan == uend);}/* * area-specifier        = ";" phone-context-tag "=" phone-context-ident * phone-context-tag     = "phone-context" * phone-context-ident   = network-prefix / private-prefix * network-prefix        = global-network-prefix / local-network-prefix * global-network-prefix = "+" 1*phonedigit * local-network-prefix  = 1*(phonedigit / dtmf-digit / pause-character) * private-prefix        = (%x21-22 / %x24-27 / %x2C / %x2F / %x3A / *                          %x3C-40 / %x45-4F / %x51-56 / %x58-60 / *                          %x65-6F / %x71-76 / %x78-7E) *                          *(%x21-3A / %x3C-7E) * phonedigit            = DIGIT / visual-separator * visual-separator      = "-" / "." / "(" / ")" * pause-character       = one-second-pause / wait-for-dial-tone * one-second-pause      = "p" * wait-for-dial-tone    = "w" * dtmf-digit            = "*" / "#" / "A" / "B" / "C" / "D" */static intsip_uri_parse_tel_areaspe(char *scan, char *uend){	int	uri_hexValue;	if (scan == uend)		return (0);	/* parse global-network-prefix */	if (*scan == '+') {		++scan;		if (scan == uend)			return (0);		while (scan < uend && SIP_URI_ISPHONEDIGIT(*scan))			++scan;	/* parse local-network-prefix */	} else if (SIP_URI_ISPHONEDIGIT(*scan) || SIP_URI_ISDTMFDIGIT(*scan) ||	    sip_uri_isEscapedPound(&scan, uend) ||	    *scan == 'p' || *scan == 'w') {		++scan;		while (scan < uend &&		    (SIP_URI_ISPHONEDIGIT(*scan) ||		    SIP_URI_ISDTMFDIGIT(*scan) ||		    sip_uri_isEscapedPound(&scan, uend) ||		    *scan == 'p' || *scan == 'w')) {			++scan;		}	} else {	/*	 * parse private-prefix	 *	 * any characters allowed in RFC 2806 that are not allowed in	 * the user part of the SIP URI MUST be escaped	 *	 * private-prefix	= (! $ & ', / = ? _	 *			EFGHIJKLMNOQRSTUVXYZ efghijklmnoqrstuvxyz	 *			{ } | ~ [ ] \ ^  ` " % : < > @)	 *			*(%x21-3A / %x3C-7E)	 *	 * following characters are allowed in RFC 2806 and	 * the user part of SIP URI	 *  ! $ & ', / = ? _ EFGHIJKLMNOQRSTUVXYZ efghijklmnoqrstuvxyz	 */		if (*scan == '!' || *scan == '$' || *scan == '&' ||		    *scan == '\'' || *scan == ',' || *scan == '/' ||		    *scan == '=' || *scan == '?' || *scan == '_' ||		    (*scan >= 'E' && *scan <= 'Z' &&		    *scan != 'P' && *scan != 'W') ||		    (*scan >= 'e' && *scan <= 'z' &&		    *scan != 'p' && *scan != 'w')) {			++scan;		} else {			uri_hexValue = sip_uri_hexVal(scan, uend);			if (uri_hexValue == 0x21 || uri_hexValue == 0x22 ||			    (uri_hexValue >= 0x24 && uri_hexValue <= 0x27) ||			    uri_hexValue == 0x2c || uri_hexValue == 0x2f ||			    uri_hexValue == 0x3a ||			    (uri_hexValue >= 0x3c && uri_hexValue <= 0x40) ||			    (uri_hexValue >= 0x45 && uri_hexValue <= 0x4f) ||			    (uri_hexValue >= 0x51 && uri_hexValue <= 0x56) ||			    (uri_hexValue >= 0x58 && uri_hexValue <= 0x60) ||			    (uri_hexValue >= 0x65 && uri_hexValue <= 0x6f) ||			    (uri_hexValue >= 0x71 && uri_hexValue <= 0x76) ||			    (uri_hexValue >= 0x78 && uri_hexValue <= 0x7e)) {				scan += 3;			} else {				return (0);			}		}		/* parse *(%x21-3A / %x3C-7E) */		while (scan < uend) {			if (SIP_URI_ISUNRESERVED(*scan) ||			    (SIP_URI_ISUSER(*scan) && *scan != ';')) {				++scan;			} else {				uri_hexValue = sip_uri_hexVal(scan, uend);				if (uri_hexValue >= 0x21 &&				    uri_hexValue <= 0x7e &&				    uri_hexValue != 0x3b) {					scan += 3;				} else {					return (0);				}

⌨️ 快捷键说明

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