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

📄 sip_parser.c

📁 基于sip协议的网络电话源码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* $Id: sip_parser.c 1229 2007-04-29 18:13:20Z 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_parser.h>#include <pjsip/sip_uri.h>#include <pjsip/sip_msg.h>#include <pjsip/sip_auth_parser.h>#include <pjsip/sip_errno.h>#include <pjsip/sip_transport.h>        /* rdata structure */#include <pjlib-util/scanner.h>#include <pjlib-util/string.h>#include <pj/except.h>#include <pj/log.h>#include <pj/hash.h>#include <pj/os.h>#include <pj/pool.h>#include <pj/string.h>#include <pj/ctype.h>#include <pj/assert.h>#define ALNUM#define RESERVED	    ";/?:@&=+$,"#define MARK		    "-_.!~*'()"#define UNRESERVED	    ALNUM MARK#define ESCAPED		    "%"#define USER_UNRESERVED	    "&=+$,;?/"#define PASS		    "&=+$,"#define TOKEN		    "-.!%*_`'~+"   /* '=' was removed for parsing 					    * param */#define HOST		    "_-."#define HEX_DIGIT	    "abcdefABCDEF"#define PARAM_CHAR	    "[]/:&+$" UNRESERVED ESCAPED#define HNV_UNRESERVED	    "[]/?:+$"#define HDR_CHAR	    HNV_UNRESERVED UNRESERVED ESCAPED#define PJSIP_VERSION		"SIP/2.0"#define UNREACHED(expr)#define IS_NEWLINE(c)	((c)=='\r' || (c)=='\n')#define IS_SPACE(c)	((c)==' ' || (c)=='\t')/* * Header parser records. */typedef struct handler_rec{    char		  hname[PJSIP_MAX_HNAME_LEN+1];    pj_size_t		  hname_len;    pj_uint32_t		  hname_hash;    pjsip_parse_hdr_func *handler;} handler_rec;static handler_rec handler[PJSIP_MAX_HEADER_TYPES];static unsigned handler_count;static int parser_is_initialized;/* * URI parser records. */typedef struct uri_parser_rec{    pj_str_t		     scheme;    pjsip_parse_uri_func    *parse;} uri_parser_rec;static uri_parser_rec uri_handler[PJSIP_MAX_URI_TYPES];static unsigned uri_handler_count;/* * Global vars (also extern). */int PJSIP_SYN_ERR_EXCEPTION;const pj_str_t  pjsip_USER_STR      = { "user", 4};const pj_str_t  pjsip_METHOD_STR    = { "method", 6};const pj_str_t  pjsip_TRANSPORT_STR = { "transport", 9};const pj_str_t  pjsip_MADDR_STR     = { "maddr", 5 };const pj_str_t  pjsip_LR_STR        = { "lr", 2 };const pj_str_t  pjsip_SIP_STR       = { "sip", 3 };const pj_str_t  pjsip_SIPS_STR      = { "sips", 4 };const pj_str_t  pjsip_TEL_STR       = { "tel", 3 };const pj_str_t  pjsip_BRANCH_STR    = { "branch", 6 };const pj_str_t  pjsip_TTL_STR       = { "ttl", 3 };const pj_str_t  pjsip_RECEIVED_STR  = { "received", 8 };const pj_str_t  pjsip_Q_STR         = { "q", 1 };const pj_str_t  pjsip_EXPIRES_STR   = { "expires", 7 };const pj_str_t  pjsip_TAG_STR       = { "tag", 3 };const pj_str_t  pjsip_RPORT_STR     = { "rport", 5};/* Character Input Specification buffer. */static pj_cis_buf_t cis_buf;/* Character Input Specifications. */pj_cis_t    pjsip_HOST_SPEC,	        /* For scanning host part. */	    pjsip_DIGIT_SPEC,	        /* Decimal digits */	    pjsip_ALPHA_SPEC,	        /* Alpha (A-Z, a-z) */	    pjsip_ALNUM_SPEC,	        /* Decimal + Alpha. */	    pjsip_TOKEN_SPEC,	        /* Token. */	    pjsip_TOKEN_SPEC_ESC,	/* Token without '%' character */	    pjsip_HEX_SPEC,	        /* Hexadecimal digits. */	    pjsip_PARAM_CHAR_SPEC,      /* For scanning pname (or pvalue when                                         * it's not quoted.) */	    pjsip_PARAM_CHAR_SPEC_ESC,	/* The variant without escaped char */	    pjsip_HDR_CHAR_SPEC,	/* Chars in hname or hvalue */	    pjsip_HDR_CHAR_SPEC_ESC,	/* Variant without escaped char */	    pjsip_PROBE_USER_HOST_SPEC, /* Hostname characters. */	    pjsip_PASSWD_SPEC,	        /* Password. */	    pjsip_PASSWD_SPEC_ESC,	/* Variant without escaped char */	    pjsip_USER_SPEC,	        /* User */	    pjsip_USER_SPEC_ESC,	/* Variant without escaped char */	    pjsip_NOT_COMMA_OR_NEWLINE, /* Array separator. */	    pjsip_NOT_NEWLINE,		/* For eating up header.*/	    pjsip_DISPLAY_SPEC;         /* Used when searching for display name                                         * in URL. *//* * Forward decl. */static pjsip_msg *  int_parse_msg( pjsip_parse_ctx *ctx, 				   pjsip_parser_err_report *err_list);static void	    int_parse_param( pj_scanner *scanner, 				     pj_pool_t *pool,				     pj_str_t *pname, 				     pj_str_t *pvalue,				     unsigned option);static void	    int_parse_uri_param( pj_scanner *scanner, 					 pj_pool_t *pool,					 pj_str_t *pname, 					 pj_str_t *pvalue,					 unsigned option);static void	    int_parse_hparam( pj_scanner *scanner,				      pj_pool_t *pool,				      pj_str_t *hname,				      pj_str_t *hvalue );static void         int_parse_req_line( pj_scanner *scanner, 					pj_pool_t *pool,					pjsip_request_line *req_line);static int          int_is_next_user( pj_scanner *scanner);static void	    int_parse_status_line( pj_scanner *scanner, 					   pjsip_status_line *line);static void	    int_parse_user_pass( pj_scanner *scanner, 					 pj_pool_t *pool,					 pj_str_t *user, 					 pj_str_t *pass);static void	    int_parse_uri_host_port( pj_scanner *scanner, 					     pj_str_t *p_host, 					     int *p_port);static pjsip_uri *  int_parse_uri_or_name_addr( pj_scanner *scanner, 					        pj_pool_t *pool,                                                 unsigned option);static void*	    int_parse_sip_url( pj_scanner *scanner, 				         pj_pool_t *pool,				         pj_bool_t parse_params);static pjsip_name_addr *                    int_parse_name_addr( pj_scanner *scanner, 					 pj_pool_t *pool );static void	    parse_hdr_end( pj_scanner *scanner );static pjsip_hdr*   parse_hdr_accept( pjsip_parse_ctx *ctx );static pjsip_hdr*   parse_hdr_allow( pjsip_parse_ctx *ctx );static pjsip_hdr*   parse_hdr_call_id( pjsip_parse_ctx *ctx);static pjsip_hdr*   parse_hdr_contact( pjsip_parse_ctx *ctx);static pjsip_hdr*   parse_hdr_content_len( pjsip_parse_ctx *ctx );static pjsip_hdr*   parse_hdr_content_type( pjsip_parse_ctx *ctx );static pjsip_hdr*   parse_hdr_cseq( pjsip_parse_ctx *ctx );static pjsip_hdr*   parse_hdr_expires( pjsip_parse_ctx *ctx );static pjsip_hdr*   parse_hdr_from( pjsip_parse_ctx *ctx );static pjsip_hdr*   parse_hdr_max_forwards( pjsip_parse_ctx *ctx);static pjsip_hdr*   parse_hdr_min_expires( pjsip_parse_ctx *ctx );static pjsip_hdr*   parse_hdr_rr( pjsip_parse_ctx *ctx );static pjsip_hdr*   parse_hdr_route( pjsip_parse_ctx *ctx );static pjsip_hdr*   parse_hdr_require( pjsip_parse_ctx *ctx );static pjsip_hdr*   parse_hdr_retry_after( pjsip_parse_ctx *ctx );static pjsip_hdr*   parse_hdr_supported( pjsip_parse_ctx *ctx );static pjsip_hdr*   parse_hdr_to( pjsip_parse_ctx *ctx );static pjsip_hdr*   parse_hdr_unsupported( pjsip_parse_ctx *ctx );static pjsip_hdr*   parse_hdr_via( pjsip_parse_ctx *ctx );static pjsip_hdr*   parse_hdr_generic_string( pjsip_parse_ctx *ctx);/* Convert non NULL terminated string to integer. */static unsigned long pj_strtoul_mindigit(const pj_str_t *str,                                          unsigned mindig){    unsigned long value;    unsigned i;    value = 0;    for (i=0; i<(unsigned)str->slen; ++i) {	value = value * 10 + (str->ptr[i] - '0');    }    for (; i<mindig; ++i) {	value = value * 10;    }    return value;}/* Case insensitive comparison */#define parser_stricmp(s1, s2)  (s1.slen!=s2.slen || pj_stricmp_alnum(&s1, &s2))/* Get a token and unescape */PJ_INLINE(void) parser_get_and_unescape(pj_scanner *scanner, pj_pool_t *pool,					const pj_cis_t *spec, 					const pj_cis_t *unesc_spec,					pj_str_t *token){#if defined(PJSIP_UNESCAPE_IN_PLACE) && PJSIP_UNESCAPE_IN_PLACE!=0    PJ_UNUSED_ARG(pool);    PJ_UNUSED_ARG(spec);    pj_scan_get_unescape(scanner, unesc_spec, token);#else    PJ_UNUSED_ARG(unesc_spec);    pj_scan_get(scanner, spec, token);    *token = pj_str_unescape(pool, token);#endif}/* Syntax error handler for parser. */static void on_syntax_error(pj_scanner *scanner){    PJ_UNUSED_ARG(scanner);    PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);}/* Concatenate unrecognized params into single string. */void pjsip_concat_param_imp( pj_str_t *param, pj_pool_t *pool, 			     const pj_str_t *pname, const pj_str_t *pvalue,                              int sepchar){    char *new_param, *p;    int len;    len = param->slen + pname->slen + pvalue->slen + 3;    p = new_param = pj_pool_alloc(pool, len);        if (param->slen) {	int old_len = param->slen;	pj_memcpy(p, param->ptr, old_len);	p += old_len;    }    *p++ = (char)sepchar;    pj_memcpy(p, pname->ptr, pname->slen);    p += pname->slen;    if (pvalue->slen) {	*p++ = '=';	pj_memcpy(p, pvalue->ptr, pvalue->slen);	p += pvalue->slen;    }    *p = '\0';        param->ptr = new_param;    param->slen = p - new_param;}/* Concatenate unrecognized params into single string. */static void concat_param( pj_str_t *param, pj_pool_t *pool, 			  const pj_str_t *pname, const pj_str_t *pvalue ){    pjsip_concat_param_imp(param, pool, pname, pvalue, ';');}/* Initialize static properties of the parser. */static pj_status_t init_parser(){    pj_status_t status;    /*     * Syntax error exception number.     */    status = pj_exception_id_alloc("PJSIP syntax error", 				   &PJSIP_SYN_ERR_EXCEPTION);    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);    /*     * Init character input spec (cis)     */    pj_cis_buf_init(&cis_buf);    status = pj_cis_init(&cis_buf, &pjsip_DIGIT_SPEC);    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);    pj_cis_add_num(&pjsip_DIGIT_SPEC);        status = pj_cis_init(&cis_buf, &pjsip_ALPHA_SPEC);    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);    pj_cis_add_alpha( &pjsip_ALPHA_SPEC );        status = pj_cis_init(&cis_buf, &pjsip_ALNUM_SPEC);    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);    pj_cis_add_alpha( &pjsip_ALNUM_SPEC );    pj_cis_add_num( &pjsip_ALNUM_SPEC );    status = pj_cis_init(&cis_buf, &pjsip_NOT_NEWLINE);    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);    pj_cis_add_str(&pjsip_NOT_NEWLINE, "\r\n");    pj_cis_invert(&pjsip_NOT_NEWLINE);    status = pj_cis_init(&cis_buf, &pjsip_NOT_COMMA_OR_NEWLINE);    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);    pj_cis_add_str( &pjsip_NOT_COMMA_OR_NEWLINE, ",\r\n");    pj_cis_invert(&pjsip_NOT_COMMA_OR_NEWLINE);    status = pj_cis_dup(&pjsip_TOKEN_SPEC, &pjsip_ALNUM_SPEC);    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);    pj_cis_add_str( &pjsip_TOKEN_SPEC, TOKEN);    status = pj_cis_dup(&pjsip_TOKEN_SPEC_ESC, &pjsip_TOKEN_SPEC);    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);    pj_cis_del_str(&pjsip_TOKEN_SPEC_ESC, "%");    status = pj_cis_dup(&pjsip_HOST_SPEC, &pjsip_ALNUM_SPEC);    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);    pj_cis_add_str( &pjsip_HOST_SPEC, HOST);    status = pj_cis_dup(&pjsip_HEX_SPEC, &pjsip_DIGIT_SPEC);    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);    pj_cis_add_str( &pjsip_HEX_SPEC, HEX_DIGIT);    status = pj_cis_dup(&pjsip_PARAM_CHAR_SPEC, &pjsip_ALNUM_SPEC);    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);    pj_cis_add_str(&pjsip_PARAM_CHAR_SPEC, PARAM_CHAR);    status = pj_cis_dup(&pjsip_PARAM_CHAR_SPEC_ESC, &pjsip_PARAM_CHAR_SPEC);    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);    pj_cis_del_str(&pjsip_PARAM_CHAR_SPEC_ESC, ESCAPED);    status = pj_cis_dup(&pjsip_HDR_CHAR_SPEC, &pjsip_ALNUM_SPEC);    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);    pj_cis_add_str(&pjsip_HDR_CHAR_SPEC, HDR_CHAR);    status = pj_cis_dup(&pjsip_HDR_CHAR_SPEC_ESC, &pjsip_HDR_CHAR_SPEC);    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);    pj_cis_del_str(&pjsip_HDR_CHAR_SPEC_ESC, ESCAPED);    status = pj_cis_dup(&pjsip_USER_SPEC, &pjsip_ALNUM_SPEC);    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);    pj_cis_add_str( &pjsip_USER_SPEC, UNRESERVED ESCAPED USER_UNRESERVED );    status = pj_cis_dup(&pjsip_USER_SPEC_ESC, &pjsip_USER_SPEC);    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);    pj_cis_del_str( &pjsip_USER_SPEC_ESC, ESCAPED);    status = pj_cis_dup(&pjsip_PASSWD_SPEC, &pjsip_ALNUM_SPEC);    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);    pj_cis_add_str( &pjsip_PASSWD_SPEC, UNRESERVED ESCAPED PASS);    status = pj_cis_dup(&pjsip_PASSWD_SPEC_ESC, &pjsip_PASSWD_SPEC);    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);    pj_cis_del_str( &pjsip_PASSWD_SPEC_ESC, ESCAPED);    status = pj_cis_init(&cis_buf, &pjsip_PROBE_USER_HOST_SPEC);    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);    pj_cis_add_str( &pjsip_PROBE_USER_HOST_SPEC, "@ \n>");    pj_cis_invert( &pjsip_PROBE_USER_HOST_SPEC );    status = pj_cis_init(&cis_buf, &pjsip_DISPLAY_SPEC);    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);    pj_cis_add_str( &pjsip_DISPLAY_SPEC, ":\r\n<");    pj_cis_invert(&pjsip_DISPLAY_SPEC);    /*     * Register URI parsers.     */    status = pjsip_register_uri_parser("sip", &int_parse_sip_url);    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);    status = pjsip_register_uri_parser("sips", &int_parse_sip_url);    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);    /*     * Register header parsers.     */    status = pjsip_register_hdr_parser( "Accept", NULL, &parse_hdr_accept);    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);    status = pjsip_register_hdr_parser( "Allow", NULL, &parse_hdr_allow);    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);    status = pjsip_register_hdr_parser( "Call-ID", "i", &parse_hdr_call_id);    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);    status = pjsip_register_hdr_parser( "Contact", "m", &parse_hdr_contact);    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);    status = pjsip_register_hdr_parser( "Content-Length", "l",                                         &parse_hdr_content_len);    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);    status = pjsip_register_hdr_parser( "Content-Type", "c",                                         &parse_hdr_content_type);    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);    status = pjsip_register_hdr_parser( "CSeq", NULL, &parse_hdr_cseq);    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);    status = pjsip_register_hdr_parser( "Expires", NULL, &parse_hdr_expires);    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);    status = pjsip_register_hdr_parser( "From", "f", &parse_hdr_from);    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);    status = pjsip_register_hdr_parser( "Max-Forwards", NULL,                                         &parse_hdr_max_forwards);    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);    status = pjsip_register_hdr_parser( "Min-Expires", NULL,                                         &parse_hdr_min_expires);    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);    status = pjsip_register_hdr_parser( "Record-Route", NULL, &parse_hdr_rr);    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);    status = pjsip_register_hdr_parser( "Route", NULL, &parse_hdr_route);    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);    status = pjsip_register_hdr_parser( "Require", NULL, &parse_hdr_require);    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);    status = pjsip_register_hdr_parser( "Retry-After", NULL,                                         &parse_hdr_retry_after);    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);    status = pjsip_register_hdr_parser( "Supported", "k",                                         &parse_hdr_supported);    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);    status = pjsip_register_hdr_parser( "To", "t", &parse_hdr_to);    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);    status = pjsip_register_hdr_parser( "Unsupported", NULL,                                         &parse_hdr_unsupported);    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);    status = pjsip_register_hdr_parser( "Via", "v", &parse_hdr_via);    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);    /*      * Register auth parser.      */    status = pjsip_auth_init_parser();    return status;}void init_sip_parser(void){    pj_enter_critical_section();    if (++parser_is_initialized == 1) {	init_parser();    }    pj_leave_critical_section();}void deinit_sip_parser(void){    pj_enter_critical_section();    if (--parser_is_initialized == 0) {	/* Clear header handlers */	pj_bzero(handler, sizeof(handler));	handler_count = 0;	/* Clear URI handlers */	pj_bzero(uri_handler, sizeof(uri_handler));	uri_handler_count = 0;    }    pj_leave_critical_section();}/* Compare the handler record with header name, and return: * - 0  if handler match. * - <0 if handler is 'less' than the header name. * - >0 if handler is 'greater' than header name. */PJ_INLINE(int) compare_handler( const handler_rec *r1, 				const char *name, 				pj_size_t name_len,				pj_uint32_t hash ){    PJ_UNUSED_ARG(name_len);    /* Compare hashed value. */    if (r1->hname_hash < hash)	return -1;    if (r1->hname_hash > hash)	return 1;    /* Compare length. */    /*    if (r1->hname_len < name_len)	return -1;    if (r1->hname_len > name_len)	return 1;     */    /* Equal length and equal hash. compare the strings. */    return pj_memcmp(r1->hname, name, name_len);

⌨️ 快捷键说明

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