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

📄 sip_parser.c

📁 基于sip协议的网络电话源码
💻 C
📖 第 1 页 / 共 4 页
字号:
}/* Register one handler for one header name. */static pj_status_t int_register_parser( const char *name,                                         pjsip_parse_hdr_func *fptr ){    unsigned	pos;    handler_rec rec;    if (handler_count >= PJ_ARRAY_SIZE(handler)) {	pj_assert(!"Too many handlers!");	return PJ_ETOOMANY;    }    /* Initialize temporary handler. */    rec.handler = fptr;    rec.hname_len = strlen(name);    if (rec.hname_len >= sizeof(rec.hname)) {	pj_assert(!"Header name is too long!");	return PJ_ENAMETOOLONG;    }    /* Copy name. */    pj_memcpy(rec.hname, name, rec.hname_len);    rec.hname[rec.hname_len] = '\0';    /* Calculate hash value. */    rec.hname_hash = pj_hash_calc(0, rec.hname, rec.hname_len);    /* Get the pos to insert the new handler. */    for (pos=0; pos < handler_count; ++pos) {	int d;	d = compare_handler(&handler[pos], rec.hname, rec.hname_len,                             rec.hname_hash);	if (d == 0) {	    pj_assert(0);	    return PJ_EEXISTS;	}	if (d > 0) {	    break;	}    }    /* Shift handlers. */    if (pos != handler_count) {	pj_memmove( &handler[pos+1], &handler[pos],                     (handler_count-pos)*sizeof(handler_rec));    }    /* Add new handler. */    pj_memcpy( &handler[pos], &rec, sizeof(handler_rec));    ++handler_count;    return PJ_SUCCESS;}/* Register parser handler. If both header name and short name are valid, * then two instances of handler will be registered. */PJ_DEF(pj_status_t) pjsip_register_hdr_parser( const char *hname,					       const char *hshortname,					       pjsip_parse_hdr_func *fptr){    unsigned i, len;    char hname_lcase[PJSIP_MAX_HNAME_LEN+1];    pj_status_t status;    /* Check that name is not too long */    len = pj_ansi_strlen(hname);    if (len > PJSIP_MAX_HNAME_LEN) {	pj_assert(!"Header name is too long!");	return PJ_ENAMETOOLONG;    }    /* Register the normal Mixed-Case name */    status = int_register_parser(hname, fptr);    if (status != PJ_SUCCESS) {	return status;    }    /* Get the lower-case name */    for (i=0; i<len; ++i) {	hname_lcase[i] = (char)pj_tolower(hname[i]);    }    hname_lcase[len] = '\0';    /* Register the lower-case version of the name */    status = int_register_parser(hname_lcase, fptr);    if (status != PJ_SUCCESS) {	return status;    }        /* Register the shortname version of the name */    if (hshortname) {        status = int_register_parser(hshortname, fptr);        if (status != PJ_SUCCESS) 	    return status;    }    return PJ_SUCCESS;}/* Find handler to parse the header name. */static pjsip_parse_hdr_func * find_handler_imp(pj_uint32_t  hash, 					       const pj_str_t *hname){    handler_rec *first;    int		 comp;    unsigned	 n;    /* Binary search for the handler. */    comp = -1;    first = &handler[0];    n = handler_count;    for (; n > 0; ) {	unsigned half = n / 2;	handler_rec *mid = first + half;	comp = compare_handler(mid, hname->ptr, hname->slen, hash);	if (comp < 0) {	    first = ++mid;	    n -= half + 1;	} else if (comp==0) {	    first = mid;	    break;	} else {	    n = half;	}    }    return comp==0 ? first->handler : NULL;}/* Find handler to parse the header name. */static pjsip_parse_hdr_func* find_handler(const pj_str_t *hname){    pj_uint32_t hash;    char hname_copy[PJSIP_MAX_HNAME_LEN];    pj_str_t tmp;    pjsip_parse_hdr_func *handler;    if (hname->slen >= PJSIP_MAX_HNAME_LEN) {	/* Guaranteed not to be able to find handler. */        return NULL;    }    /* First, common case, try to find handler with exact name */    hash = pj_hash_calc(0, hname->ptr, hname->slen);    handler = find_handler_imp(hash, hname);    if (handler)	return handler;    /* If not found, try converting the header name to lowercase and     * search again.     */    hash = pj_hash_calc_tolower(0, hname_copy, hname);    tmp.ptr = hname_copy;    tmp.slen = hname->slen;    return find_handler_imp(hash, &tmp);}/* Find URI handler. */static pjsip_parse_uri_func* find_uri_handler(const pj_str_t *scheme){    unsigned i;    for (i=0; i<uri_handler_count; ++i) {	if (parser_stricmp(uri_handler[i].scheme, (*scheme))==0)	    return uri_handler[i].parse;    }    return NULL;}/* Register URI parser. */PJ_DEF(pj_status_t) pjsip_register_uri_parser( char *scheme,					       pjsip_parse_uri_func *func){    if (uri_handler_count >= PJ_ARRAY_SIZE(uri_handler))	return PJ_ETOOMANY;    uri_handler[uri_handler_count].scheme = pj_str((char*)scheme);    uri_handler[uri_handler_count].parse = func;    ++uri_handler_count;    return PJ_SUCCESS;}/* Public function to parse SIP message. */PJ_DEF(pjsip_msg*) pjsip_parse_msg( pj_pool_t *pool,                                     char *buf, pj_size_t size,				    pjsip_parser_err_report *err_list){    pjsip_msg *msg = NULL;    pj_scanner scanner;    pjsip_parse_ctx context;    pj_scan_init(&scanner, buf, size, PJ_SCAN_AUTOSKIP_WS_HEADER,                  &on_syntax_error);    context.scanner = &scanner;    context.pool = pool;    context.rdata = NULL;    msg = int_parse_msg(&context, err_list);    pj_scan_fini(&scanner);    return msg;}/* Public function to parse as rdata.*/PJ_DEF(pjsip_msg *) pjsip_parse_rdata( char *buf, pj_size_t size,                                       pjsip_rx_data *rdata ){    pj_scanner scanner;    pjsip_parse_ctx context;    pj_scan_init(&scanner, buf, size, PJ_SCAN_AUTOSKIP_WS_HEADER,                  &on_syntax_error);    context.scanner = &scanner;    context.pool = rdata->tp_info.pool;    context.rdata = rdata;    rdata->msg_info.msg = int_parse_msg(&context, &rdata->msg_info.parse_err);    pj_scan_fini(&scanner);    return rdata->msg_info.msg;}/* Determine if a message has been received. */PJ_DEF(pj_bool_t) pjsip_find_msg( const char *buf, pj_size_t size, 				  pj_bool_t is_datagram, pj_size_t *msg_size){#if PJ_HAS_TCP    const char *hdr_end;    const char *body_start;    const char *pos;    const char *line;    int content_length = -1;    *msg_size = size;    /* For datagram, the whole datagram IS the message. */    if (is_datagram) {	return PJ_SUCCESS;    }    /* Find the end of header area by finding an empty line. */    pos = pj_ansi_strstr(buf, "\n\r\n");    if (pos == NULL) {	return PJSIP_EPARTIALMSG;    }     hdr_end = pos+1;    body_start = pos+3;    /* Find "Content-Length" header the hard way. */    line = pj_ansi_strchr(buf, '\n');    while (line && line < hdr_end) {	++line;	if ( ((*line=='C' || *line=='c') &&               strnicmp_alnum(line, "Content-Length", 14) == 0) ||	     ((*line=='l' || *line=='L') &&               (*(line+1)==' ' || *(line+1)=='\t' || *(line+1)==':')))	{	    /* Try to parse the header. */	    pj_scanner scanner;	    PJ_USE_EXCEPTION;	    pj_scan_init(&scanner, (char*)line, hdr_end-line, 			 PJ_SCAN_AUTOSKIP_WS_HEADER, &on_syntax_error);	    PJ_TRY {		pj_str_t str_clen;		/* Get "Content-Length" or "L" name */		if (*line=='C' || *line=='c')		    pj_scan_advance_n(&scanner, 14, PJ_TRUE);		else if (*line=='l' || *line=='L')		    pj_scan_advance_n(&scanner, 1, PJ_TRUE);		/* Get colon */		if (pj_scan_get_char(&scanner) != ':') {		    PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);		}		/* Get number */		pj_scan_get(&scanner, &pjsip_DIGIT_SPEC, &str_clen);		/* Get newline. */		pj_scan_get_newline(&scanner);		/* Found a valid Content-Length header. */		content_length = pj_strtoul(&str_clen);	    }	    PJ_CATCH_ANY {		content_length = -1;	    }	    PJ_END	    pj_scan_fini(&scanner);	}	/* Found valid Content-Length? */	if (content_length != -1)	    break;	/* Go to next line. */	line = pj_ansi_strchr(line, '\n');    }    /* Found Content-Length? */    if (content_length == -1) {	return PJSIP_EMISSINGHDR;    }    /* Enough packet received? */    *msg_size = (body_start - buf) + content_length;    return (*msg_size) <= size ? PJ_SUCCESS : PJSIP_EPARTIALMSG;#else    PJ_UNUSED_ARG(buf);    PJ_UNUSED_ARG(is_datagram);    *msg_size = size;    return PJ_SUCCESS;#endif}/* Public function to parse URI */PJ_DEF(pjsip_uri*) pjsip_parse_uri( pj_pool_t *pool, 					 char *buf, pj_size_t size,					 unsigned option){    pj_scanner scanner;    pjsip_uri *uri = NULL;    PJ_USE_EXCEPTION;    pj_scan_init(&scanner, buf, size, 0, &on_syntax_error);        PJ_TRY {	uri = int_parse_uri_or_name_addr(&scanner, pool, option);    }    PJ_CATCH_ANY {	uri = NULL;    }    PJ_END;    /* Must have exhausted all inputs. */    if (pj_scan_is_eof(&scanner) || IS_NEWLINE(*scanner.curptr)) {	/* Success. */	pj_scan_fini(&scanner);	return uri;    }    /* Still have some characters unparsed. */    pj_scan_fini(&scanner);    return NULL;}/* Generic function to print message body. * This assumes that the 'data' member points to a contigous memory where the  * actual body is laid. */static int generic_print_body (pjsip_msg_body *msg_body,                                char *buf, pj_size_t size){    pjsip_msg_body *body = msg_body;    if (size < body->len)	return 0;    pj_memcpy (buf, body->data, body->len);    return body->len;}/* Internal function to parse SIP message */static pjsip_msg *int_parse_msg( pjsip_parse_ctx *ctx,				 pjsip_parser_err_report *err_list){    pj_bool_t parsing_headers;    pjsip_msg *msg = NULL;    pj_str_t hname;    pjsip_ctype_hdr *ctype_hdr = NULL;    pj_scanner *scanner = ctx->scanner;    pj_pool_t *pool = ctx->pool;    PJ_USE_EXCEPTION;    parsing_headers = PJ_FALSE;    PJ_TRY     {	if (parsing_headers)	    goto parse_headers;	/* Skip leading newlines. */	while (IS_NEWLINE(*scanner->curptr)) {	    pj_scan_get_newline(scanner);	}	/* Check if we still have valid packet.	 * Sometimes endpoints just send blank (CRLF) packets just to keep	 * NAT bindings open.	 */	if (pj_scan_is_eof(scanner))	    return NULL;	/* Parse request or status line */	if (pj_scan_stricmp_alnum( scanner, PJSIP_VERSION, 7) == 0) {	    msg = pjsip_msg_create(pool, PJSIP_RESPONSE_MSG);	    int_parse_status_line( scanner, &msg->line.status );	} else {	    msg = pjsip_msg_create(pool, PJSIP_REQUEST_MSG);	    int_parse_req_line(scanner, pool, &msg->line.req );	}	parsing_headers = PJ_TRUE;parse_headers:	/* Parse headers. */	do {	    pjsip_parse_hdr_func * handler;	    pjsip_hdr *hdr = NULL;	    /* Init hname just in case parsing fails.	     * Ref: PROTOS #2412	     */	    hname.slen = 0;	    	    /* Get hname. */	    pj_scan_get( scanner, &pjsip_TOKEN_SPEC, &hname);	    if (pj_scan_get_char( scanner ) != ':') {		PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);	    }	    	    /* Find handler. */	    handler = find_handler(&hname);	    	    /* Call the handler if found.	     * If no handler is found, then treat the header as generic	     * hname/hvalue pair.	     */	    if (handler) {		hdr = (*handler)(ctx);		/* Check if we've just parsed a Content-Type header. 		 * We will check for a message body if we've got Content-Type 		 * header.		 */		if (hdr->type == PJSIP_H_CONTENT_TYPE) {		    ctype_hdr = (pjsip_ctype_hdr*)hdr;		}	    } else {		hdr = parse_hdr_generic_string(ctx);		hdr->name = hdr->sname = hname;	    }	    		    /* Single parse of header line can produce multiple headers.	     * For example, if one Contact: header contains Contact list	     * separated by comma, then these Contacts will be split into	     * different Contact headers.	     * So here we must insert list instead of just insert one header.	     */	    pj_list_insert_nodes_before(&msg->hdr, hdr);	    	    /* Parse until EOF or an empty line is found. */	} while (!pj_scan_is_eof(scanner) && !IS_NEWLINE(*scanner->curptr));		parsing_headers = PJ_FALSE;	/* If empty line is found, eat it. */	if (!pj_scan_is_eof(scanner)) {	    if (IS_NEWLINE(*scanner->curptr)) {		pj_scan_get_newline(scanner);	    }	}	/* If we have Content-Type header, treat the rest of the message 	 * as body.	 */	if (ctype_hdr && scanner->curptr!=scanner->end) {	    pjsip_msg_body *body = pj_pool_alloc(pool, sizeof(pjsip_msg_body));	    body->content_type.type = ctype_hdr->media.type;	    body->content_type.subtype = ctype_hdr->media.subtype;	    body->content_type.param = ctype_hdr->media.param;	    body->data = scanner->curptr;	    body->len = scanner->end - scanner->curptr;	    body->print_body = &generic_print_body;	    body->clone_data = &pjsip_clone_text_data;	    msg->body = body;	}    }    PJ_CATCH_ANY     {	/* Exception was thrown during parsing. 	 * Skip until newline, and parse next header. 	 */	if (err_list) {	    pjsip_parser_err_report *err_info;	    	    err_info = pj_pool_alloc(pool, sizeof(*err_info));	    err_info->except_code = PJ_GET_EXCEPTION();	    err_info->line = scanner->line;	    /* Scanner's column is zero based, so add 1 */	    err_info->col = pj_scan_get_col(scanner) + 1;	    if (parsing_headers)		err_info->hname = hname;	    else if (msg && msg->type == PJSIP_REQUEST_MSG)		err_info->hname = pj_str("Request Line");	    else if (msg && msg->type == PJSIP_RESPONSE_MSG)		err_info->hname = pj_str("Status Line");	    else		err_info->hname.slen = 0;	    	    pj_list_insert_before(err_list, err_info);	}

⌨️ 快捷键说明

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