use crate::{
common::{
bnfcore::*,
errorparse::SipParseError,
nom_wrappers::{from_utf8_nom, take_sws},
take_sws_token,
traits::NomParser,
},
headers::{
parsers::ExtensionParser,
traits::{HeaderValueParserFn, SipHeaderParser},
GenericParams, SipRFCHeader, SipUri,
},
};
use alloc::collections::{BTreeMap, VecDeque};
use core::str;
use nom::{bytes::complete::take_while1, character::complete, sequence::tuple};
use unicase::Ascii;
#[derive(PartialEq, Debug)]
pub enum HeaderValueType {
EmptyValue,
TokenValue,
Digit,
AbsoluteURI,
QuotedValue,
AuthentificationInfo,
CSeq,
DateString,
Utf8Text,
Version,
AuthorizationDigest,
CallID,
CallInfo,
NameAddr,
Timestamp,
RetryAfter,
UserAgent,
Via,
Warning,
ExtensionHeader,
}
#[derive(PartialEq, Debug, Eq, PartialOrd, Ord)]
pub enum HeaderTagType {
PureValue,
AinfoType,
AinfoValue,
AbsoluteURI,
AuthSchema,
Username,
Domain,
Realm,
Nonce,
DigestUri,
Dresponse,
Algorithm,
Cnonce,
Opaque,
Stale,
QopValue,
NonceCount,
Number,
Method,
ID,
Host,
Port,
Star,
DisplayName,
Seconds,
Comment,
Major,
Minor,
TimveVal,
Delay,
ProtocolName,
ProtocolVersion,
ProtocolTransport,
WarnCode,
WarnAgent,
WarnText,
}
pub type HeaderTags<'a> = BTreeMap<HeaderTagType, &'a [u8]>;
#[derive(PartialEq, Debug)]
pub struct HeaderValue<'a> {
pub vstr: &'a str,
pub vtype: HeaderValueType,
vtags: Option<HeaderTags<'a>>,
sip_uri: Option<SipUri<'a>>,
}
impl<'a> HeaderValue<'a> {
pub fn create_empty_value() -> HeaderValue<'a> {
HeaderValue {
vstr: "",
vtype: HeaderValueType::EmptyValue,
vtags: None,
sip_uri: None,
}
}
pub fn new(
val: &'a [u8],
vtype: HeaderValueType,
vtags: Option<HeaderTags<'a>>,
sip_uri: Option<SipUri<'a>>,
) -> nom::IResult<&'a [u8], HeaderValue<'a>, SipParseError<'a>> {
let (_, vstr) = from_utf8_nom(val)?;
Ok((
val,
HeaderValue {
vstr: vstr,
vtype: vtype,
vtags: vtags,
sip_uri: sip_uri,
},
))
}
pub fn tags(&self) -> Option<&HeaderTags<'a>> {
self.vtags.as_ref()
}
pub fn sip_uri(&self) -> Option<&SipUri<'a>> {
self.sip_uri.as_ref()
}
}
#[derive(PartialEq, Debug)]
pub struct Header<'a> {
pub name: Ascii<&'a str>,
pub value: HeaderValue<'a>,
parameters: Option<GenericParams<'a>>,
}
impl<'a> Header<'a> {
pub fn new(
name: &'a str,
value: HeaderValue<'a>,
parameters: Option<GenericParams<'a>>,
) -> Header<'a> {
Header {
name: { Ascii::new(name) },
value: value,
parameters: parameters,
}
}
pub fn params(&self) -> Option<&GenericParams<'a>> {
self.parameters.as_ref()
}
pub fn find_parser(header_name: &'a str) -> (Option<SipRFCHeader>, HeaderValueParserFn) {
match SipRFCHeader::from_str(&header_name) {
Some(rfc_header) => (Some(rfc_header), rfc_header.get_parser()),
None => (None, ExtensionParser::take_value),
}
}
pub fn take_name(input: &'a [u8]) -> nom::IResult<&[u8], &'a str, SipParseError> {
let (input_rest, (header_name, _, _, _)) = tuple((
take_while1(is_token_char),
complete::space0,
complete::char(':'),
complete::space0,
))(input)?;
match str::from_utf8(header_name) {
Ok(hdr_str) => Ok((input_rest, hdr_str)),
Err(_) => sip_parse_error!(1, "Bad header name"),
}
}
pub fn take_value(
input: &'a [u8],
parser: HeaderValueParserFn,
) -> nom::IResult<&'a [u8], (HeaderValue<'a>, Option<GenericParams<'a>>), SipParseError<'a>>
{
let (input, _) = take_sws(input)?;
if is_crlf(input) {
return Ok((input, (HeaderValue::create_empty_value(), None)));
}
let (inp, value) = parser(input)?;
let (inp, _) = complete::space0(inp)?;
if inp.is_empty() {
return sip_parse_error!(1, "Error parse header value");
}
if inp[0] != b',' && inp[0] != b';' && inp[0] != b' ' && !is_crlf(inp) {
return sip_parse_error!(2, "Error parse header value");
}
if inp[0] == b';' {
let (inp, params) = Header::try_take_parameters(inp)?;
return Ok((inp, (value, params)));
}
Ok((inp, (value, None)))
}
fn try_take_parameters(
input: &'a [u8],
) -> nom::IResult<&'a [u8], Option<GenericParams<'a>>, SipParseError<'a>> {
if input.is_empty() || input[0] != b';' {
return Ok((input, None));
}
let (input, parameters) = GenericParams::parse(input)?;
Ok((input, Some(parameters)))
}
}
impl<'a> NomParser<'a> for Header<'a> {
type ParseResult = (Option<SipRFCHeader>, VecDeque<Header<'a>>);
fn parse(input: &'a [u8]) -> nom::IResult<&[u8], Self::ParseResult, SipParseError> {
let mut headers = VecDeque::new();
let (input, header_name) = Header::take_name(input)?;
let (rfc_type, value_parser) = Header::find_parser(header_name);
let mut inp = input;
loop {
let (input, (value, params)) = Header::take_value(inp, value_parser)?;
headers.push_back(Header::new(header_name, value, params));
if input[0] == b',' {
let (input, _) = take_sws_token::comma(input)?;
inp = input;
continue;
}
inp = input;
break;
}
Ok((inp, (rfc_type, headers)))
}
}