📄 sip_parse_uri.c
字号:
/* * 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 + -