From: Richard Whitehouse Date: Mon, 20 Nov 2017 00:08:04 +0000 (+0000) Subject: Split up parser X-Git-Url: https://git.richardwhiuk.com/?a=commitdiff_plain;h=8d410b9a57147cbb4a1a2eb076c8f6926f415d5a;p=rust-sip.git Split up parser --- diff --git a/src/parser.rs b/src/parser.rs deleted file mode 100644 index 81a9131..0000000 --- a/src/parser.rs +++ /dev/null @@ -1,1297 +0,0 @@ -use nom; -use std; - -use nom::alpha as alphas; -use nom::digit as digits; -use nom::alphanumeric as alphanumerics; - -use nom::IResult; -use nom::ErrorKind::Custom; - -use types::{PathSegment, HostPort, Host, Hostname, UriParameter, UriHeader, UriHeaders, SipUri, - AbsoluteUri, Uri, HierarchicalPath, Authority, UriPath, UserInfo, AbsolutePath, - Scheme, Method, Transport, UserParam, Version, RequestLine, StatusLine, TopLine, - Header, MediaMainType, MediaType, MediaFullType, MediaParameter, MediaRange, - GenericParam, AcceptParam, AcceptRange, Coding, Encoding, LanguageTag, LanguageRange, - Language, AlertParam, Qop, AuthenticationInfo, AuthParam, Algorithm, DigestResponse, - Credentials, CallId, Purpose, InfoParam, Info, NameAddr, ContactParam, Target, - Contact, DispositionType, Handling, DispositionParam, ContentCoding, Day, Month, Date, - Time, DateTime, ErrorUri, FromParam, From, Priority, Domain, DigestChallenge, - Challenge, OptionTag, Route, ReplyTo, RetryAfterParam, RetryAfter, Server, ToParam, - To, Protocol, SentProtocol, Received, ViaParam, Via, WarningAgent, Warning}; - -pub fn float(input: &[u8]) -> IResult<&[u8], f32> { - flat_map!(input, - recognize!(tuple!(opt!(alt!(tag!("+") | tag!("-"))), - alt!(delimited!(digits, tag!("."), opt!(digits)) | - delimited!(opt!(digits), tag!("."), digits) | - digits), - opt!(complete!(tuple!(alt!(tag!("e") | tag!("E")), - opt!(alt!(tag!("+") | tag!("-"))), - digit))))), - parse_to!(f32)) -} - -fn is_mark(c: u8) -> bool { - c == b'-' || c == b'_' || c == b'.' || c == b'!' || c == b'~' || c == b'*' || c == b'\'' || - c == b'(' || c == b')' -} - -fn is_unreserved(c: u8) -> bool { - nom::is_alphanumeric(c) || is_mark(c) -} - -fn is_reserved(c: u8) -> bool { - c == b';' || c == b'/' || c == b'?' || c == b':' || c == b'@' || c == b'&' || c == b'=' || - c == b'+' || c == b'$' || c == b',' -} - -fn is_user_unreserved(c: u8) -> bool { - is_unreserved(c) || c == b'&' || c == b'=' || c == b'+' || c == b'$' || c == b',' || - c == b';' || c == b'?' || c == b'/' -} - -fn is_password_unreserved(c: u8) -> bool { - is_unreserved(c) || c == b'=' || c == b'+' || c == b'$' || c == b',' -} - -fn is_domain_label(c: u8) -> bool { - nom::is_alphanumeric(c) || c == b'-' -} - -macro_rules! take_1 ( - ($input:expr, $submac:ident!( $($args:tt)* )) => ( - { - use nom::Slice; - let input = $input; - - match input.iter().next() { - Some(c) => { - if $submac!(*c, $($args)*) { - let res:nom::IResult<&[u8],u8> = nom::IResult::Done(input.slice(1..), *c); - res - } - else - { - nom::IResult::Error(error_position!(nom::ErrorKind::TakeWhile1, input)) - } - }, - None => { - nom::IResult::Incomplete(nom::Needed::Size(1)) - } - } - } - ); - ($input:expr, $f:expr) => ( - take_1!($input, call!($f)); - ); -); - -fn is_token(c: u8) -> bool { - nom::is_alphanumeric(c) || c == b'-' || c == b'.' || c == b'!' || c == b'%' || - c == b'*' || c == b'_' || c == b'+' || c == b'`' || c == b'\'' || c == b'~' -} - -fn is_word(c: u8) -> bool { - is_token(c) || c == b'(' || c == b')' || c == b'<' || c == b'>' || c == b':' || - c == b'\\' || c == b'"' || c == b'/' || c == b'[' || c == b']' || - c == b'?' || c == b'{' || c == b'}' -} - -fn is_lhex_digit(c: u8) -> bool { - nom::is_digit(c) || (c >= b'a' && c <= b'f') -} - -named!(token>, many1!(take_1!(is_token))); -named!(word>, many1!(take_1!(is_word))); - -named!(method, alt!( -// RFC 3261 - tag!("INVITE") => { |_| Method::INVITE } | - tag!("ACK") => { |_| Method::ACK } | - tag!("OPTIONS") => { |_| Method::OPTIONS } | - tag!("BYE") => { |_| Method::BYE } | - tag!("CANCEL") => { |_| Method::CANCEL } | - tag!("REGISTER") => { |_| Method::REGISTER } | -// Extensions - tag!("MESSAGE") => { |_| Method::MESSAGE } | - tag!("REFER") => { |_| Method::REFER } | - tag!("SUBSCRIBE") => { |_| Method::SUBSCRIBE } | - tag!("NOTIFY") => { |_| Method::NOTIFY } | - token => { |method| Method::Extension(method) } -)); - -named!(alpha<&[u8], u8>, take_1!(nom::is_alphabetic)); -named!(alphanumeric<&[u8], u8>, take_1!(nom::is_alphanumeric)); -named!(digit<&[u8], u8>, take_1!(nom::is_digit)); -named!(hex<&[u8], u8>, take_1!(nom::is_hex_digit)); -named!(lhex<&[u8], u8>, take_1!(is_lhex_digit)); - -fn escaped(input: &[u8]) -> IResult<&[u8], u8> { - let result = preceded!(input, tag!(b"%"), pair!(hex, hex)); - - match result { - IResult::Done(left, (a, b)) => { - let value: u8 = ((a - (b'0' as u8)) << 4) + (b - b'0'); - IResult::Done(left, value) - } - IResult::Incomplete(a) => IResult::Incomplete(a), - IResult::Error(a) => IResult::Error(a), - } -} - -named!(user_unreserved<&[u8], u8>, take_1!(is_user_unreserved)); -named!(password_unreserved<&[u8], u8>, take_1!(is_password_unreserved)); - -// The BNF splits unreserved and user unreserved, but that's just a waste -named!(user<&[u8], Vec>, many1!(alt!( - user_unreserved | - escaped))); - -named!(password<&[u8], Vec>, many1!(alt!( - password_unreserved | - escaped))); - -named!(userinfo<&[u8], (Vec, Option>)>, terminated!( - pair!( - user, - opt!(preceded!(tag!(b":"), password))), - tag!(b"@"))); - -named!(domain_label<&[u8], Vec>, alt!( - alphanumerics => { |a : &[u8]| a.to_vec() } | - tuple!( - alphanumeric, - take_while1!(is_domain_label), - alphanumeric) => { |(a, b, c) : (u8, &[u8], u8)| { - let mut v = Vec::with_capacity(b.len() + 2); - v.push(a); - v.extend_from_slice(b); - v.push(c); - v - }})); - -named!(top_label<&[u8], Vec>, alt!( - alphas => { |a : &[u8]| a.to_vec() } | - tuple!( - alpha, - take_while1!(is_domain_label)) => { |(a, b) : (u8, &[u8])| { - let mut v = Vec::with_capacity(b.len() + 2); - v.push(a); - v.extend_from_slice(b); - v - }})); - -named!(hostname<&[u8], Hostname>, tuple!( - many0!(terminated!(domain_label, tag!(b"."))), - terminated!(top_label, opt!(tag!(b"."))))); - -fn number(input: &[u8]) -> IResult<&[u8], O> - where O: std::str::FromStr -{ - match digits(input) { - IResult::Done(left, num_str) => { - if let Ok(num_utf8) = std::str::from_utf8(num_str) { - if let Ok(num_i) = num_utf8.parse::() { - IResult::Done(left, num_i) - } else { - IResult::Error(Custom(1)) - } - } else { - IResult::Error(Custom(2)) - } - } - IResult::Error(e) => IResult::Error(e), - IResult::Incomplete(i) => IResult::Incomplete(i), - } -} - -named!(ipv4_address<&[u8], (u8, u8, u8, u8)>, tuple!( - number, - preceded!(tag!(b"."), number), - preceded!(tag!(b"."), number), - preceded!(tag!(b"."), number))); - -fn is_ipv6_char(c: u8) -> bool { - nom::is_hex_digit(c) || c == b':' -} - -named!(ipv6_address<&[u8], Vec>, delimited!( - tag!(b"["), - many1!(take_1!(is_ipv6_char)), - tag!(b"]"))); - -named!(host, alt!( - hostname => { |h| Host::Hostname(h) } | - ipv4_address => { |(a, b, c, d)| Host::Ipv4Address(a,b,c,d) } | - ipv6_address => { |i| Host::Ipv6Address(i) } -)); - -named!(hostport<&[u8], HostPort>, tuple!( - host, - opt!(preceded!(tag!(":"), number)))); - -named!(transport_param, alt!( - tag!("tcp") => { |_| Transport::Tcp } | - tag!("udp") => { |_| Transport::Udp } | - tag!("sctp") => { |_| Transport::Sctp } | - tag!("tls") => { |_| Transport::Tls } | - token => { |token| Transport::Other(token) } -)); - -named!(user_param, alt!( - tag!("phone") => { |_| UserParam::Phone } | - tag!("ip") => { |_| UserParam::Ip } | - token => { |token| UserParam::Other(token) })); - -fn is_param_unreserved(c: u8) -> bool { - is_unreserved(c) || c == b'[' || c == b']' || c == b'/' || c == b':' || c == b'&' || - c == b'+' || c == b'$' -} - -named!(param<&[u8], Vec>, many1!(alt!( - take_1!(is_param_unreserved) | - escaped))); - -named!(uri_parameter, alt!( - preceded!(tag!("transport="), transport_param) => { - |transport| UriParameter::Transport(transport) - } | - preceded!(tag!("user="), user_param) => { |user| UriParameter::User(user) } | - preceded!(tag!("method="), method) => { |method| UriParameter::Method(method) } | - preceded!(tag!(b"ttl="), number) => { |ttl| UriParameter::Ttl(ttl) } | - preceded!(tag!("maddr="), recognize!(host)) => { - |host : &[u8]| UriParameter::Maddr(host.to_vec()) - } | - tag!("lr") => { |ttl| UriParameter::Lr } | - pair!(param, opt!(preceded!(tag!(b"="), param))) => { - |(key, value)| - UriParameter::Other { - key: key, - value: value - } - } -)); - -named!(uri_parameters<&[u8], Vec>, many0!( - preceded!(char!(';'), uri_parameter))); - -fn is_header_unreserved(c: u8) -> bool { - is_unreserved(c) || c == b'[' || c == b']' || c == b'/' || c == b'?' || c == b':' || - c == b'+' || c == b'$' -} - -named!(hname<&[u8], Vec>, many1!(alt!( - take_1!(is_header_unreserved) | - escaped))); - -named!(hvalue<&[u8], Vec>, many1!(alt!( - take_1!(is_header_unreserved) | - escaped))); - -named!(uri_header<&[u8], UriHeader>, separated_pair!( - hname, - tag!(b"="), - hvalue)); - -named!(uri_headers<&[u8], UriHeaders>, preceded!( - char!('?'), - separated_nonempty_list!( - tag!(b"&"), - uri_header))); - -type _SipUri = (Option, HostPort, Vec, Option); - -named!(sip_uri<&[u8], _SipUri>, preceded!( - tag!("sip:"), - tuple!( - opt!(userinfo), - hostport, - uri_parameters, - opt!(uri_headers) - ))); - -named!(sips_uri<&[u8], _SipUri>, preceded!( - tag!("sips:"), - tuple!( - opt!(userinfo), - hostport, - uri_parameters, - opt!(uri_headers) - ))); - -type _SipUriNp = (Option, HostPort); - -named!(sip_uri_np<&[u8], _SipUriNp>, preceded!( - tag!("sip:"), - tuple!( - opt!(userinfo), - hostport - ))); - -named!(sips_uri_np<&[u8], _SipUriNp>, preceded!( - tag!("sips:"), - tuple!( - opt!(userinfo), - hostport - ))); - -fn is_scheme_unreserved(c: u8) -> bool { - nom::is_alphanumeric(c) || c == b'+' || c == b'-' || c == b'.' -} - -named!(scheme<&[u8], Scheme>, tuple!( - alpha, - many0!(take_1!(is_scheme_unreserved)))); - -fn is_path_char(c: u8) -> bool { - is_unreserved(c) || c == b':' || c == b'@' || c == b'&' || c == b'=' || c == b'+' || - c == b'$' || c == b',' -} - -named!(path_param<&[u8], Vec>, many0!(alt!( - escaped | - take_1!(is_path_char)))); - -named!(path_segment<&[u8], PathSegment>, pair!( - many0!(take_1!(is_path_char)), - opt!(preceded!(tag!(b";"), path_param)))); - -named!(srvr<&[u8], (Option, HostPort)>, tuple!( - opt!(userinfo), - hostport)); - -fn is_reg_name_char(c: u8) -> bool { - is_unreserved(c) || c == b':' || c == b';' || c == b'$' || c == b'@' || c == b'&' || - c == b'=' || c == b'+' || c == b',' -} - -named!(reg_name<&[u8], Vec>, many1!(alt!( - take_1!(is_reg_name_char) | - escaped))); - -named!(authority<&[u8], Authority>, alt!( - srvr => { |(u, h)| Authority::Server { userinfo: u, hostport: h } } | - reg_name => { |n| Authority::Name(n) } )); - -named!(abs_path<&[u8], AbsolutePath>, many1!( - preceded!(char!('/'), path_segment))); - -named!(net_path<&[u8], (Authority, Option)>, preceded!(tag!("//"), pair!( - authority, - opt!(abs_path)))); - -named!(query<&[u8], Vec>, many0!(uric)); - -named!(hier_part<&[u8], (HierarchicalPath, Option>)>, tuple!( - alt!( - net_path => { |(a, p)| HierarchicalPath::Network{ authority: a, path: p } } | - abs_path => { |p| HierarchicalPath::Absolute(p) } - ), - opt!(preceded!(char!('?'), query)))); - -fn is_uri_char_no_slash(c: u8) -> bool { - is_unreserved(c) || c == b';' || c == b'?' || c == b':' || c == b'@' || c == b'&' || - c == b'=' || c == b'+' || c == b'$' || c == b',' -} - -named!(uric_no_slash<&[u8], u8>, alt!( - take_1!(is_uri_char_no_slash) | - escaped)); - -fn is_uri_char(c: u8) -> bool { - is_unreserved(c) || is_reserved(c) -} - -named!(uric<&[u8], u8>, alt!( - take_1!(is_uri_char) | - escaped)); - -named!(opaque_part<&[u8], (u8, Vec)>, pair!( - uric_no_slash, - many0!(uric))); - -named!(absolute_uri<&[u8], AbsoluteUri>, separated_pair!( - scheme, - char!(':'), - alt!( - hier_part => { |(h,q)| UriPath::Hierarchical { path: h, query: q } } | - opaque_part => { |(b, o)| UriPath::Opaque(b, o) } - ))); - -named!(uri<&[u8], Uri>, alt!( - sip_uri => { |(u, hp, p, h)| Uri::Sip(SipUri { - user_info: u, - host_port: hp, - params: p, - headers: h }) } | - sips_uri => { |(u, hp, p, h)| Uri::Sips(SipUri { - user_info: u, - host_port: hp, - params: p, - headers: h }) } | - absolute_uri => { |(s, p)| Uri::Generic { - scheme: s, - path: p } } -)); - -// Variant without URI parameters or header parameters -named!(uri_np<&[u8], Uri>, alt!( - sip_uri_np => { |(u, hp)| Uri::Sip(SipUri { - user_info: u, - host_port: hp, - params: vec![], - headers: None }) } | - sips_uri_np => { |(u, hp)| Uri::Sips(SipUri { - user_info: u, - host_port: hp, - params: vec![], - headers: None }) } | - absolute_uri => { |(s, p)| Uri::Generic { - scheme: s, - path: p } } -)); - -named!(sip_version<&[u8], Version>, preceded!( - tag!("SIP/"), - dbg_dmp!(separated_pair!( - dbg_dmp!(number), - dbg_dmp!(tag!(b".")), - dbg_dmp!(number))))); - -named!(request_line<&[u8], (Method, Uri, Version)>, tuple!( - method, - delimited!( - tag!(" "), - uri, - tag!(" ")), - sip_version)); - -fn is_reason_phrase_char(c: u8) -> bool { - is_reserved(c) || is_unreserved(c) || c == b' ' || c == b'\t' -} - -named!(reason_phrase>, many0!(alt!( - escaped | - take_1!(is_reason_phrase_char)))); - -named!(status_line<&[u8], (Version, u16, Vec)>, tuple!( - sip_version, - delimited!( - tag!(" "), - number, - tag!(" ") - ), - reason_phrase)); - -named!(pub top_line, alt!( - request_line => { |(m,u,v)| TopLine::RequestLine(RequestLine { - method: m, - uri: u, - version: v - })} | - status_line => { |(v, c, r)| TopLine::StatusLine(StatusLine { - version: v, - code: c, - reason: r - })})); - -/// Headers - -fn is_spacetab(c: u8) -> bool { - c == b' ' || c == b'\t' -} - -fn is_whitespace(c: u8) -> bool { - is_spacetab(c) -} - -named!(spacetab, take_1!(is_spacetab)); - -named!(crlf, tag!(b"\r\n")); - -named!(lws<(Option<(Vec, &[u8])>, Vec)>, pair!( - opt!(pair!(many0!(take_1!(is_whitespace)), crlf)), - many1!(take_1!(is_whitespace)))); - -named!(sws, &[u8])>, Vec)>>, opt!(lws)); - -named!(hcolon, delimited!( - many0!(spacetab), - tag!(b":"), - sws)); - -// Accept Header - -named!(media_main_type, alt!( -// Discrete Types - tag!(b"text") => { |_| MediaMainType::Text } | - tag!(b"image") => { |_| MediaMainType::Image } | - tag!(b"audio") => { |_| MediaMainType::Audio } | - tag!(b"video") => { |_| MediaMainType::Video } | - tag!(b"application") => { |_| MediaMainType::Application } | -// Composite Types - tag!(b"message") => { |_| MediaMainType::Message } | - tag!(b"multipart") => { |_| MediaMainType::Multipart } | -// Extensions - token => { |x| MediaMainType::Extension(x) })); - -// We don't bother splitting IANA, IETF and x- token types. -use self::token as media_subtype; - -use self::token as media_attribute; - -fn is_qdtext_char(c: u8) -> bool { - c == 0x21 || (c >= 0x23 && c <= 0x5b) || (c >= 0x5d && c <= 0x7e) -} - -named!(qdtext, take_1!(is_qdtext_char)); - -fn is_qdpair_char(c: u8) -> bool { - c <= 0x09 || c == 0x0B || c == 0x0C || (c >= 0x0E && c <= 0x7f) -} - -named!(qdpair, preceded!( - tag!("\\"), - take_1!(is_qdpair_char))); - -named!(quoted_string>, delimited!( - tag!(b"\""), - many0!(alt!( - qdtext | - qdpair)), - tag!(b"\""))); - -named!(media_value>, alt!( - token | - quoted_string)); - -named!(media_parameter, separated_pair!( - media_attribute, - tag!(b"="), - media_value)); - -named!(media_type, separated_pair!( - media_main_type, - tag!(b"/"), - media_subtype)); - -named!(media_range, tuple!( - alt!( - tag!(b"*/*") => { |_| MediaFullType::All } | - terminated!(media_main_type, tag!(b"/*")) => { |x| MediaFullType::Partial(x) } | /**/ - media_type => { |(t, st)| MediaFullType::Specific(t, st) }), - many0!( - preceded!(tag!(b";"), media_parameter)))); - -named!(generic_param, separated_pair!( - token, - tag!(b"="), - opt!(token))); - -use self::float as qvalue; - -named!(qparam, preceded!(tag!(b"q="), qvalue)); - -named!(accept_param, alt!( - qparam => { |x| AcceptParam::Qvalue(x) } | - generic_param => { |x| AcceptParam::Generic(x) })); - -named!(accept_range, tuple!( - media_range, - many0!(preceded!( - tag!(b";"), - accept_param)))); - -named!(accept_header>, preceded!( - terminated!(tag!(b"Accept"), hcolon), - separated_nonempty_list!( - tag!(b","), - accept_range))); - -named!(codings, alt!( - tag!(b"*") => { |_| Coding::All } | - token => { |t| Coding::Content(t) } -)); - -named!(encoding, tuple!( - codings, - many0!(preceded!( - tag!(b";"), - accept_param)))); - -named!(accept_encoding_header>, preceded!( - terminated!(tag!(b"Accept-Encoding"), hcolon), - separated_nonempty_list!( - tag!(b","), - encoding))); - -named!(language_token>, many1!(alpha)); - -named!(language_tag, separated_nonempty_list!( - tag!(b"-"), - language_token)); - -named!(language_range, alt!( - tag!(b"*") => { |_| LanguageRange::All } | - language_tag => { |x : LanguageTag| LanguageRange::Range(x) })); - -named!(language, tuple!( - language_range, - many0!(preceded!( - tag!(b";"), - accept_param)))); - -named!(accept_language_header>, preceded!( - terminated!(tag!(b"Accept-Language"), hcolon), - separated_nonempty_list!( - tag!(b","), - language))); - -named!(alert_param, tuple!( - delimited!( - tag!(b"<"), - absolute_uri, - tag!(b">") - ), - many0!(generic_param))); - -named!(alert_info_header>, preceded!( - terminated!(tag!(b"Alert-Info"), hcolon), - separated_nonempty_list!( - tag!(b","), - alert_param))); - -named!(allow_header>, preceded!( - terminated!(tag!(b"Allow"), hcolon), - separated_nonempty_list!( - tag!(b","), - method))); - -named!(nextnonce>, preceded!( - tag!(b"nc="), - quoted_string)); - -named!(qop_value, alt!( - tag!(b"auth") => { |x| Qop::Auth } | - tag!(b"auth-init") => { |x| Qop::AuthInit } | - token => { |x| Qop::Token(x) })); - -named!(message_qop, preceded!( - tag!(b"qop="), - qop_value)); - -named!(response_digest>, delimited!( - tag!(b"\""), - many0!(hex), - tag!(b"\""))); - -named!(response_auth>, preceded!( - tag!(b"rspauth="), - response_digest)); - -named!(cnonce>, preceded!( - tag!(b"cnonce="), - quoted_string)); - -named!(nc_value>, many1!(lhex)); - -named!(nonce_count>, preceded!( - tag!(b"nc="), - nc_value)); - -named!(ainfo, alt!( - nextnonce => { |n| AuthenticationInfo::NextNonce(n) } | - message_qop => { |m| AuthenticationInfo::MessageQop(m) } | - response_auth => { |r| AuthenticationInfo::ResponseAuth(r) } | - cnonce => { |c| AuthenticationInfo::Cnonce(c) } | - nonce_count => { |n| AuthenticationInfo::NonceCount(n) })); - -named!(authentication_info_header>, preceded!( - terminated!(tag!(b"Authentication-Info"), hcolon), - separated_nonempty_list!( - tag!(b","), - ainfo))); - -named!(username>, preceded!( - tag!(b"username="), - quoted_string)); - -named!(realm>, preceded!( - tag!(b"realm="), - quoted_string)); - -named!(nonce>, preceded!( - tag!(b"nonce="), - quoted_string)); - -named!(digest_uri>, preceded!( - tag!(b"digest_uri="), - quoted_string)); - -named!(dresponse>, preceded!( - tag!(b"response="), - response_digest)); - -named!(algorithm, alt!( - tag!("MD5") => { |_| Algorithm::Md5 } | - tag!("MD5-sess") => { |_| Algorithm::Md5Session } | - token => { |t| Algorithm::Token(t) } -)); - -named!(opaque>, preceded!( - tag!(b"opaque="), - quoted_string)); - -named!(auth_param, separated_pair!( - token, - tag!(b"="), - alt!( - token | - quoted_string))); - -named!(digest_response>, many1!(alt!( - username => { |u| DigestResponse::Username(u) } | - realm => { |r| DigestResponse::Realm(r) } | - nonce => { |n| DigestResponse::Nonce(n) } | - digest_uri => { |d| DigestResponse::DigestUri(d) } | - dresponse => { |d| DigestResponse::Response(d) } | - algorithm => { |a| DigestResponse::Algorithm(a) } | - cnonce => { |c| DigestResponse::Cnonce(c) } | - opaque => { |o| DigestResponse::Opaque(o) } | - message_qop => { |m| DigestResponse::MessageQop(m) } | - nonce_count => { |n| DigestResponse::NonceCount(n) } | - auth_param => { |(k, v)| DigestResponse::AuthParam(k, v) }))); - -named!(other_response<(Vec, Vec)>, separated_pair!( - token, - tag!(b" "), - separated_nonempty_list!( - tag!(b","), - auth_param))); - -named!(credentials, alt!( - preceded!( - tag!(b"Digest "), - digest_response) => { |d| Credentials::Digest(d) } | - other_response => { |(s,p)| Credentials::Other(s, p) })); - -named!(authorization_header, preceded!( - terminated!(tag!(b"Authorization"), hcolon), - credentials)); - -named!(call_id, tuple!( - word, - opt!(preceded!( - tag!(b"@"), - word)))); - -named!(call_id_header, preceded!( - terminated!(alt!(tag!(b"Call-ID") | tag!(b"i")), hcolon), - call_id)); - -named!(purpose, alt!( - tag!(b"icon") => { |_| Purpose::Icon } | - tag!(b"info") => { |_| Purpose::Info } | - tag!(b"card") => { |_| Purpose::Card } | - token => { |t| Purpose::Token(t) })); - -named!(info_param, alt!( - preceded!( - tag!(b"purpose="), - purpose) => { |p| InfoParam::Purpose(p) } | - generic_param => { |g| InfoParam::Generic(g) })); - -named!(info, tuple!( - delimited!( - tag!(b"<"), - absolute_uri, - tag!(b">") - ), - many0!(preceded!( - tag!(b";"), - info_param)))); - -named!(call_info_header>, preceded!( - terminated!(tag!(b"Call-Info"), hcolon), - separated_nonempty_list!( - tag!(","), - info))); - -named!(display_name>, alt!( - token | - quoted_string)); - -named!(name_addr, tuple!( - opt!(display_name), - delimited!( - tag!(b"<"), - uri, - tag!(b">")))); - -named!(expires, preceded!( - tag!(b"expires="), - number)); - -named!(contact_param, alt!( - qparam => {|q| ContactParam::Qvalue(q) } | - expires => {|e| ContactParam::Expires(e) } | - generic_param => {|g| ContactParam::Generic(g) })); - -named!(target, - alt!( - name_addr => { |(n, u)| Target::Name(n, u) } | -// With this target variant, parameters conflict - so they aren't allowed -// See RFC 3261 Section 20.10 - uri_np => { |u| Target::Uri(u) })); - -named!(contact_target<(Target, Vec)>, tuple!( - target, - many0!(preceded!( - tag!(b";"), - contact_param - )))); - -named!(contact_header, preceded!( - terminated!(alt!(tag!(b"Contact") | tag!(b"m")), hcolon), - alt!( - tag!(b"*") => { |_| Contact::Star } | - separated_nonempty_list!( - tag!(","), - contact_target) => { |c| Contact::Contact(c) }))); - -named!(disp_type, alt!( - tag!(b"render") => { |_| DispositionType::Render } | - tag!(b"session") => { |_| DispositionType::Session } | - tag!(b"icon") => { |_| DispositionType::Icon } | - tag!(b"alert") => { |_| DispositionType::Alert } | - token => { |t| DispositionType::Token(t) } -)); - -named!(handling, alt!( - tag!(b"optional") => { |_| Handling::Optional } | - tag!(b"required") => { |_| Handling::Required } | - token => { |t| Handling::Token(t) })); - -named!(disp_param, alt!( - preceded!(tag!(b"handling="), handling) => { |h| DispositionParam::Handling(h) } | - generic_param => { |g| DispositionParam::Generic(g) })); - -named!(content_disposition_header<(DispositionType, Vec)>, preceded!( - terminated!(tag!(b"Content-Disposition"), hcolon), - tuple!( - disp_type, - many0!(preceded!( - tag!(b";"), - disp_param))))); - -named!(content_encoding_header>, preceded!( - terminated!(alt!(tag!(b"Content-Encoding") | tag!(b"e")), hcolon), - separated_nonempty_list!( - tag!(b","), - token))); - -named!(content_language_header>, preceded!( - terminated!(tag!(b"Content-Language"), hcolon), - separated_nonempty_list!( - tag!(b","), - language_tag))); - -named!(content_length_header, preceded!( - terminated!(alt!(tag!(b"Content-Length") | tag!(b"l")), hcolon), - number)); - -named!(content_type_header, preceded!( - terminated!(alt!(tag!(b"Content-Type") | tag!(b"c")), hcolon), - media_type)); - -named!(cseq_header<(u32, Method)>, preceded!( - terminated!(tag!(b"CSeq"), hcolon), - separated_pair!( - number, - tag!(" "), - method))); - -named!(wkday, alt!( - tag!(b"Mon") => { |_| Day::Monday } | - tag!(b"Tue") => { |_| Day::Tuesday } | - tag!(b"Wed") => { |_| Day::Wednesday } | - tag!(b"Thu") => { |_| Day::Thursday } | - tag!(b"Fri") => { |_| Day::Friday } | - tag!(b"Sat") => { |_| Day::Saturday } | - tag!(b"Sun") => { |_| Day::Sunday })); - -named!(month, alt!( - tag!(b"Jan") => { |_| Month::January } | - tag!(b"Feb") => { |_| Month::February } | - tag!(b"Mar") => { |_| Month::March } | - tag!(b"Apr") => { |_| Month::April } | - tag!(b"May") => { |_| Month::May } | - tag!(b"Jun") => { |_| Month::June } | - tag!(b"Jul") => { |_| Month::July } | - tag!(b"Aug") => { |_| Month::August } | - tag!(b"Sep") => { |_| Month::September } | - tag!(b"Oct") => { |_| Month::October } | - tag!(b"Nov") => { |_| Month::November } | - tag!(b"Dec") => { |_| Month::December })); - -named!(date, tuple!( - terminated!(number, tag!(b" ")), - terminated!(month, tag!(b" ")), - number)); - -named!(time