📄 sip_parse.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.c 1.35 06/08/16 SMI"#include "sip_msg.h"#include "sip_miscdefs.h"#include "sip_parse_generic.h"/* Parse SIP/2.0 string */static intsip_get_protocol_version(_sip_header_t *sip_header, sip_proto_version_t *sip_proto_version){ if (sip_skip_white_space(sip_header) != 0) return (1); if (!strncasecmp(sip_header->sip_hdr_current, SIP, strlen(SIP))) { sip_proto_version->name.sip_str_ptr = sip_header->sip_hdr_current; sip_proto_version->name.sip_str_len = strlen(SIP); if (sip_find_token(sip_header, SIP_SLASH) != 0) return (1); if (sip_skip_white_space(sip_header) != 0) return (1); sip_proto_version->version.sip_str_ptr = sip_header->sip_hdr_current; while (isdigit(*sip_header->sip_hdr_current)) { sip_header->sip_hdr_current++; if (sip_header->sip_hdr_current >= sip_header->sip_hdr_end) { return (1); } } if (*sip_header->sip_hdr_current != SIP_PERIOD) return (1); sip_header->sip_hdr_current++; if (!isdigit(*sip_header->sip_hdr_current)) return (1); while (isdigit(*sip_header->sip_hdr_current)) { sip_header->sip_hdr_current++; if (sip_header->sip_hdr_current >= sip_header->sip_hdr_end) { return (1); } } sip_proto_version->version.sip_str_len = sip_header->sip_hdr_current - sip_proto_version->version.sip_str_ptr; return (0); } return (1);}/* * Warning = "Warning" HCOLON warning-value *(COMMA warning-value) * warning-value = warn-code SP warn-agent SP warn-text * warn-code = 3DIGIT * warn-agent = hostport | pseudonym ; * the name or pseudonym of the server adding; * the Warning header, for use in debugging * warn-text = quoted-string * pseudonym = token */intsip_parse_warn_header(_sip_header_t *sip_header, sip_parsed_header_t **header){ sip_parsed_header_t *parsed_header; int ret; sip_hdr_value_t *value = NULL; sip_hdr_value_t *last_value = NULL; if (sip_header == NULL || header == NULL) return (EINVAL); /* check if already parsed */ if (sip_header->sip_hdr_parsed != NULL) { *header = sip_header->sip_hdr_parsed; return (0); } *header = NULL; assert(sip_header->sip_hdr_start == sip_header->sip_hdr_current); if (sip_parse_goto_values(sip_header) != 0) return (EPROTO); parsed_header = calloc(1, sizeof (sip_parsed_header_t)); if (parsed_header == NULL) return (ENOMEM); parsed_header->sip_header = sip_header; while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) { value = calloc(1, sizeof (sip_hdr_value_t)); if (value == NULL) { sip_free_phdr(parsed_header); return (ENOMEM); } if (last_value != NULL) last_value->sip_next_value = value; else parsed_header->value = (sip_value_t *)value; value->sip_value_start = sip_header->sip_hdr_current; value->sip_value_header = parsed_header; ret = sip_atoi(sip_header, &value->warn_code); if (ret != 0 || value->warn_code < 100 || value->warn_code > 999) { value->sip_value_state = SIP_VALUE_BAD; goto get_next_val; } if (sip_skip_white_space(sip_header) != 0) { value->sip_value_state = SIP_VALUE_BAD; goto get_next_val; } value->warn_agt_ptr = sip_header->sip_hdr_current; if (sip_find_token(sip_header, SIP_QUOTE) == 0) { /* get warning agent */ sip_header->sip_hdr_current--; (void) sip_reverse_skip_white_space(sip_header); value->warn_agt_len = sip_header->sip_hdr_current - value->warn_agt_ptr - 1; if (value->warn_agt_len <= 0) { value->warn_agt_ptr = NULL; value->sip_value_state = SIP_VALUE_BAD; } if (sip_find_token(sip_header, SIP_QUOTE) != 0) { value->sip_value_state = SIP_VALUE_BAD; goto get_next_val; } value->warn_text_ptr = sip_header->sip_hdr_current; if (sip_find_token(sip_header, SIP_QUOTE) == 0) { value->warn_text_len = sip_header->sip_hdr_current - value->warn_text_ptr - 1; } else { value->sip_value_state = SIP_VALUE_BAD; goto get_next_val; } } else /* warning text must present */ value->sip_value_state = SIP_VALUE_BAD;get_next_val: if (sip_find_token(sip_header, SIP_COMMA) != 0) break; value->sip_value_end = sip_header->sip_hdr_current - 1; last_value = value; (void) sip_skip_white_space(sip_header); } *header = parsed_header; sip_header->sip_hdr_parsed = *header; return (0);}/* * Date = "Date" HCOLON SIPdate * SIPdate = wkday "," SP date1 SP time SP "GMT" * date1 = 2DIGIT SP mnth SP 4DIGIT; day month year * time = 2DIGIT ":" 2DIGIT ":" 2DIGIT * wkday = "Mon" | "Tue" | "Wed" | "Thu" | "Fri" | "Sat" | "Sun" * month = "Jan" | "Feb" etc */intsip_parse_date_header(_sip_header_t *sip_header, sip_parsed_header_t **header){ sip_parsed_header_t *parsed_header; int r; sip_hdr_value_t *value = NULL; if (sip_header == NULL || header == NULL) return (EINVAL); /* check if already parsed */ if (sip_header->sip_hdr_parsed != NULL) { *header = sip_header->sip_hdr_parsed; return (0); } *header = NULL; assert(sip_header->sip_hdr_start == sip_header->sip_hdr_current); if (sip_parse_goto_values(sip_header) != 0) return (EPROTO); parsed_header = calloc(1, sizeof (sip_parsed_header_t)); if (parsed_header == NULL) return (ENOMEM); parsed_header->sip_header = sip_header; value = calloc(1, sizeof (sip_hdr_value_t)); if (value == NULL) { sip_free_phdr(parsed_header); return (ENOMEM); } parsed_header->value = (sip_value_t *)value; value->sip_value_start = sip_header->sip_hdr_current; value->sip_value_header = parsed_header; value->date_wd_ptr = sip_header->sip_hdr_current; if (sip_find_token(sip_header, SIP_COMMA) == 0) { value->date_wd_len = sip_header->sip_hdr_current - value->date_wd_ptr - 1; sip_header->sip_hdr_current++; if (sip_skip_white_space(sip_header) != 0) { value->sip_value_state = SIP_VALUE_BAD; return (EPROTO); } } else { value->sip_value_state = SIP_VALUE_BAD; return (EPROTO); } if (sip_skip_white_space(sip_header) != 0) { value->sip_value_state = SIP_VALUE_BAD; return (EPROTO); } r = sip_atoi(sip_header, &value->date_d); if (r != 0) { value->sip_value_state = SIP_VALUE_BAD; return (EPROTO); } if (sip_skip_white_space(sip_header) != 0) { value->sip_value_state = SIP_VALUE_BAD; return (EPROTO); } value->date_m_ptr = sip_header->sip_hdr_current; if (sip_find_token(sip_header, SIP_SP) == 0) { value->date_m_len = sip_header->sip_hdr_current - value->date_m_ptr - 1; } else { value->sip_value_state = SIP_VALUE_BAD; return (EPROTO); } r = sip_atoi(sip_header, &value->date_y); if (r != 0) { value->sip_value_state = SIP_VALUE_BAD; return (EPROTO); } if (sip_skip_white_space(sip_header) != 0) { value->sip_value_state = SIP_VALUE_BAD; return (EPROTO); } value->date_t_ptr = sip_header->sip_hdr_current; if (sip_find_token(sip_header, SIP_SP) == 0) { value->date_t_len = sip_header->sip_hdr_current - value->date_t_ptr - 1; } else { value->sip_value_state = SIP_VALUE_BAD; return (EPROTO); } value->date_tz_ptr = sip_header->sip_hdr_current; /* minus 2 to get rid of the CRLF */ value->date_tz_len = sip_header->sip_hdr_end - sip_header->sip_hdr_current - 2; *header = parsed_header; sip_header->sip_hdr_parsed = *header; return (0);}intsip_parse_allow_events_header(_sip_header_t *sip_header, sip_parsed_header_t **header){ int r; r = sip_parse_hdr_parser1(sip_header, header, (char)NULL); sip_header->sip_hdr_parsed = *header; return (r);}intsip_parse_event_header(_sip_header_t *sip_header, sip_parsed_header_t **header){ int r; r = sip_parse_hdr_parser1(sip_header, header, (char)NULL); sip_header->sip_hdr_parsed = *header; return (r);}intsip_parse_substate_header(_sip_header_t *sip_header, sip_parsed_header_t **header){ int r; r = sip_parse_hdr_parser1(sip_header, header, (char)NULL); sip_header->sip_hdr_parsed = *header; return (r);}/* * Accept = "Accept" HCOLON [ accept-range *(COMMA accept-range) ] * accept-range = media-range *(SEMI accept-param) * media-range = ("* / *" | (m-type SLASH "*") | (m-type SLASH m-subtype)) * *(SEMI m-param) * accept-param = ("q" EQUAL qvalue) | generic-param * qvalue = ("0" ["." 0*3DIGIT]) | ("1" ["." 0*3DIGIT]) * generic-param = token [ EQUAL gen-value] * gen-value = token | host | quoted-str * * EXAMPLE: * Accept: application/sdp; level = 1, application/x-private, text/html */intsip_parse_acpt_header(_sip_header_t *sip_header, sip_parsed_header_t **header){ int r; if (!sip_is_empty_hdr(sip_header)) { r = sip_parse_hdr_empty(sip_header, header); return (r); } r = sip_parse_hdr_parser1(sip_header, header, SIP_SLASH); sip_header->sip_hdr_parsed = *header; return (r);}/* * SYNTAX: * Accept-Encoding = "Accept-Encoding" ":" 1#(codings [ ";" "q" "=" qval]) * codings = (content-coding | "*") * content-coding = token * * EXAMPLE: * Accept-Encoding: gzip; q = 1.0, identity; q = 0.5 */intsip_parse_acpt_encode_header(_sip_header_t *sip_header, sip_parsed_header_t **header){ int r; r = sip_parse_hdr_parser1(sip_header, header, (char)NULL); sip_header->sip_hdr_parsed = *header; return (r);}/* * SYNTAX: * Accept-Language = "Accept-Language" ":" [ lang * (COMMA lang) ] * lang = lang-range *(SEMI accept-param) * lang-range = ((1*8ALPHA * ("-" 1*8ALPHA)) | "*" * * DEFAULT: * empty header field is eqivalent to "identity" * * EXAMPLE: * Accept-Language: da, en-gb; q = 0.8, en; q = 0.5 * */intsip_parse_acpt_lang_header(_sip_header_t *sip_header, sip_parsed_header_t **header){ int r; if (!sip_is_empty_hdr(sip_header)) { r = sip_parse_hdr_empty(sip_header, header); return (r); } r = sip_parse_hdr_parser1(sip_header, header, (char)NULL); sip_header->sip_hdr_parsed = *header; return (r);}/* * SYNTAX: * Alert-Info = "Alert-Info" ":" alert-param *(COMMA alert-param) * alert-param = LAQUOT absoluteURI RAQUOT * (SEMI generic-param) * * EXAMPLE: * Alert-Info: < http://www.example.com/sounds/moo.waw > * */intsip_parse_alert_header(_sip_header_t *sip_header, sip_parsed_header_t **header){ int r; r = sip_parse_hdr_parser3(sip_header, header, SIP_STR_VAL, B_TRUE); sip_header->sip_hdr_parsed = *header; return (r);}/* * SYNTAX: * Allow = "Allow" ":" method-name1[, method-name2..] * * EXAMPLE: * Allow: INVITE, ACK, CANCEL * */intsip_parse_allow_header(_sip_header_t *hdr, sip_parsed_header_t **phdr){ sip_parsed_header_t *parsed_header; sip_hdr_value_t *value = NULL; sip_hdr_value_t *last_value = NULL; int len; int i; if (hdr == NULL || phdr == NULL) return (EINVAL); /* check if previously parsed */ if (hdr->sip_hdr_parsed != NULL) { *phdr = hdr->sip_hdr_parsed; return (0); } *phdr = NULL; assert(hdr->sip_hdr_start == hdr->sip_hdr_current); if (sip_parse_goto_values(hdr) != 0) return (EPROTO); parsed_header = calloc(1, sizeof (sip_parsed_header_t)); if (parsed_header == NULL) return (ENOMEM); parsed_header->sip_header = hdr; while (hdr->sip_hdr_current < hdr->sip_hdr_end) { value = calloc(1, sizeof (sip_hdr_value_t)); if (value == NULL) { sip_free_phdr(parsed_header); return (ENOMEM); } if (last_value != NULL) last_value->sip_next_value = value; else parsed_header->value = (sip_value_t *)value; value->sip_value_start = hdr->sip_hdr_current; value->sip_value_header = parsed_header; if (sip_find_separator(hdr, SIP_COMMA, (char)NULL, (char)NULL) == 0) { len = hdr->sip_hdr_current - value->sip_value_start; for (i = 1; i < MAX_SIP_METHODS; i++) { if (strncmp(sip_methods[i].name, value->sip_value_start, len) == 0) break; } if (i >= MAX_SIP_METHODS) { value->int_val = 0; value->sip_value_state = SIP_VALUE_BAD; goto next_val; } value->int_val = i; } else { len = hdr->sip_hdr_current - value->sip_value_start; for (i = 1; i < MAX_SIP_METHODS; i++) { if (strncmp(sip_methods[i].name, value->sip_value_start, len) == 0) break; } if (i >= MAX_SIP_METHODS) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -