+++ /dev/null
-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<Vec<u8>>, many1!(take_1!(is_token)));
-named!(word<Vec<u8>>, many1!(take_1!(is_word)));
-
-named!(method<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<u8>>, many1!(alt!(
- user_unreserved |
- escaped)));
-
-named!(password<&[u8], Vec<u8>>, many1!(alt!(
- password_unreserved |
- escaped)));
-
-named!(userinfo<&[u8], (Vec<u8>, Option<Vec<u8>>)>, terminated!(
- pair!(
- user,
- opt!(preceded!(tag!(b":"), password))),
- tag!(b"@")));
-
-named!(domain_label<&[u8], Vec<u8>>, 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<u8>>, 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<O>(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::<O>() {
- 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<u8>>, delimited!(
- tag!(b"["),
- many1!(take_1!(is_ipv6_char)),
- tag!(b"]")));
-
-named!(host<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<Transport>, 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<UserParam>, 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<u8>>, many1!(alt!(
- take_1!(is_param_unreserved) |
- escaped)));
-
-named!(uri_parameter<UriParameter>, 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<UriParameter>>, 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<u8>>, many1!(alt!(
- take_1!(is_header_unreserved) |
- escaped)));
-
-named!(hvalue<&[u8], Vec<u8>>, 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<UserInfo>, HostPort, Vec<UriParameter>, Option<UriHeaders>);
-
-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<UserInfo>, 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<u8>>, 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<UserInfo>, 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<u8>>, 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<AbsolutePath>)>, preceded!(tag!("//"), pair!(
- authority,
- opt!(abs_path))));
-
-named!(query<&[u8], Vec<u8>>, many0!(uric));
-
-named!(hier_part<&[u8], (HierarchicalPath, Option<Vec<u8>>)>, 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<u8>)>, 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<Vec<u8>>, many0!(alt!(
- escaped |
- take_1!(is_reason_phrase_char))));
-
-named!(status_line<&[u8], (Version, u16, Vec<u8>)>, tuple!(
- sip_version,
- delimited!(
- tag!(" "),
- number,
- tag!(" ")
- ),
- reason_phrase));
-
-named!(pub top_line<TopLine>, 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<u8>, take_1!(is_spacetab));
-
-named!(crlf, tag!(b"\r\n"));
-
-named!(lws<(Option<(Vec<u8>, &[u8])>, Vec<u8>)>, pair!(
- opt!(pair!(many0!(take_1!(is_whitespace)), crlf)),
- many1!(take_1!(is_whitespace))));
-
-named!(sws<Option<(Option<(Vec<u8>, &[u8])>, Vec<u8>)>>, opt!(lws));
-
-named!(hcolon, delimited!(
- many0!(spacetab),
- tag!(b":"),
- sws));
-
-// Accept Header
-
-named!(media_main_type<MediaMainType>, 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<u8>, take_1!(is_qdtext_char));
-
-fn is_qdpair_char(c: u8) -> bool {
- c <= 0x09 || c == 0x0B || c == 0x0C || (c >= 0x0E && c <= 0x7f)
-}
-
-named!(qdpair<u8>, preceded!(
- tag!("\\"),
- take_1!(is_qdpair_char)));
-
-named!(quoted_string<Vec<u8>>, delimited!(
- tag!(b"\""),
- many0!(alt!(
- qdtext |
- qdpair)),
- tag!(b"\"")));
-
-named!(media_value<Vec<u8>>, alt!(
- token |
- quoted_string));
-
-named!(media_parameter<MediaParameter>, separated_pair!(
- media_attribute,
- tag!(b"="),
- media_value));
-
-named!(media_type<MediaType>, separated_pair!(
- media_main_type,
- tag!(b"/"),
- media_subtype));
-
-named!(media_range<MediaRange>, 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<GenericParam>, separated_pair!(
- token,
- tag!(b"="),
- opt!(token)));
-
-use self::float as qvalue;
-
-named!(qparam<f32>, preceded!(tag!(b"q="), qvalue));
-
-named!(accept_param<AcceptParam>, alt!(
- qparam => { |x| AcceptParam::Qvalue(x) } |
- generic_param => { |x| AcceptParam::Generic(x) }));
-
-named!(accept_range<AcceptRange>, tuple!(
- media_range,
- many0!(preceded!(
- tag!(b";"),
- accept_param))));
-
-named!(accept_header<Vec<AcceptRange>>, preceded!(
- terminated!(tag!(b"Accept"), hcolon),
- separated_nonempty_list!(
- tag!(b","),
- accept_range)));
-
-named!(codings<Coding>, alt!(
- tag!(b"*") => { |_| Coding::All } |
- token => { |t| Coding::Content(t) }
-));
-
-named!(encoding<Encoding>, tuple!(
- codings,
- many0!(preceded!(
- tag!(b";"),
- accept_param))));
-
-named!(accept_encoding_header<Vec<Encoding>>, preceded!(
- terminated!(tag!(b"Accept-Encoding"), hcolon),
- separated_nonempty_list!(
- tag!(b","),
- encoding)));
-
-named!(language_token<Vec<u8>>, many1!(alpha));
-
-named!(language_tag<LanguageTag>, separated_nonempty_list!(
- tag!(b"-"),
- language_token));
-
-named!(language_range<LanguageRange>, alt!(
- tag!(b"*") => { |_| LanguageRange::All } |
- language_tag => { |x : LanguageTag| LanguageRange::Range(x) }));
-
-named!(language<Language>, tuple!(
- language_range,
- many0!(preceded!(
- tag!(b";"),
- accept_param))));
-
-named!(accept_language_header<Vec<Language>>, preceded!(
- terminated!(tag!(b"Accept-Language"), hcolon),
- separated_nonempty_list!(
- tag!(b","),
- language)));
-
-named!(alert_param<AlertParam>, tuple!(
- delimited!(
- tag!(b"<"),
- absolute_uri,
- tag!(b">")
- ),
- many0!(generic_param)));
-
-named!(alert_info_header<Vec<AlertParam>>, preceded!(
- terminated!(tag!(b"Alert-Info"), hcolon),
- separated_nonempty_list!(
- tag!(b","),
- alert_param)));
-
-named!(allow_header<Vec<Method>>, preceded!(
- terminated!(tag!(b"Allow"), hcolon),
- separated_nonempty_list!(
- tag!(b","),
- method)));
-
-named!(nextnonce<Vec<u8>>, preceded!(
- tag!(b"nc="),
- quoted_string));
-
-named!(qop_value<Qop>, alt!(
- tag!(b"auth") => { |x| Qop::Auth } |
- tag!(b"auth-init") => { |x| Qop::AuthInit } |
- token => { |x| Qop::Token(x) }));
-
-named!(message_qop<Qop>, preceded!(
- tag!(b"qop="),
- qop_value));
-
-named!(response_digest<Vec<u8>>, delimited!(
- tag!(b"\""),
- many0!(hex),
- tag!(b"\"")));
-
-named!(response_auth<Vec<u8>>, preceded!(
- tag!(b"rspauth="),
- response_digest));
-
-named!(cnonce<Vec<u8>>, preceded!(
- tag!(b"cnonce="),
- quoted_string));
-
-named!(nc_value<Vec<u8>>, many1!(lhex));
-
-named!(nonce_count<Vec<u8>>, preceded!(
- tag!(b"nc="),
- nc_value));
-
-named!(ainfo<AuthenticationInfo>, 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<Vec<AuthenticationInfo>>, preceded!(
- terminated!(tag!(b"Authentication-Info"), hcolon),
- separated_nonempty_list!(
- tag!(b","),
- ainfo)));
-
-named!(username<Vec<u8>>, preceded!(
- tag!(b"username="),
- quoted_string));
-
-named!(realm<Vec<u8>>, preceded!(
- tag!(b"realm="),
- quoted_string));
-
-named!(nonce<Vec<u8>>, preceded!(
- tag!(b"nonce="),
- quoted_string));
-
-named!(digest_uri<Vec<u8>>, preceded!(
- tag!(b"digest_uri="),
- quoted_string));
-
-named!(dresponse<Vec<u8>>, preceded!(
- tag!(b"response="),
- response_digest));
-
-named!(algorithm<Algorithm>, alt!(
- tag!("MD5") => { |_| Algorithm::Md5 } |
- tag!("MD5-sess") => { |_| Algorithm::Md5Session } |
- token => { |t| Algorithm::Token(t) }
-));
-
-named!(opaque<Vec<u8>>, preceded!(
- tag!(b"opaque="),
- quoted_string));
-
-named!(auth_param<AuthParam>, separated_pair!(
- token,
- tag!(b"="),
- alt!(
- token |
- quoted_string)));
-
-named!(digest_response<Vec<DigestResponse>>, 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<u8>, Vec<AuthParam>)>, separated_pair!(
- token,
- tag!(b" "),
- separated_nonempty_list!(
- tag!(b","),
- auth_param)));
-
-named!(credentials<Credentials>, alt!(
- preceded!(
- tag!(b"Digest "),
- digest_response) => { |d| Credentials::Digest(d) } |
- other_response => { |(s,p)| Credentials::Other(s, p) }));
-
-named!(authorization_header<Credentials>, preceded!(
- terminated!(tag!(b"Authorization"), hcolon),
- credentials));
-
-named!(call_id<CallId>, tuple!(
- word,
- opt!(preceded!(
- tag!(b"@"),
- word))));
-
-named!(call_id_header<CallId>, preceded!(
- terminated!(alt!(tag!(b"Call-ID") | tag!(b"i")), hcolon),
- call_id));
-
-named!(purpose<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<InfoParam>, alt!(
- preceded!(
- tag!(b"purpose="),
- purpose) => { |p| InfoParam::Purpose(p) } |
- generic_param => { |g| InfoParam::Generic(g) }));
-
-named!(info<Info>, tuple!(
- delimited!(
- tag!(b"<"),
- absolute_uri,
- tag!(b">")
- ),
- many0!(preceded!(
- tag!(b";"),
- info_param))));
-
-named!(call_info_header<Vec<Info>>, preceded!(
- terminated!(tag!(b"Call-Info"), hcolon),
- separated_nonempty_list!(
- tag!(","),
- info)));
-
-named!(display_name<Vec<u8>>, alt!(
- token |
- quoted_string));
-
-named!(name_addr<NameAddr>, tuple!(
- opt!(display_name),
- delimited!(
- tag!(b"<"),
- uri,
- tag!(b">"))));
-
-named!(expires<u32>, preceded!(
- tag!(b"expires="),
- number));
-
-named!(contact_param<ContactParam>, alt!(
- qparam => {|q| ContactParam::Qvalue(q) } |
- expires => {|e| ContactParam::Expires(e) } |
- generic_param => {|g| ContactParam::Generic(g) }));
-
-named!(target<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<ContactParam>)>, tuple!(
- target,
- many0!(preceded!(
- tag!(b";"),
- contact_param
- ))));
-
-named!(contact_header<Contact>, 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<DispositionType>, 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<Handling>, alt!(
- tag!(b"optional") => { |_| Handling::Optional } |
- tag!(b"required") => { |_| Handling::Required } |
- token => { |t| Handling::Token(t) }));
-
-named!(disp_param<DispositionParam>, alt!(
- preceded!(tag!(b"handling="), handling) => { |h| DispositionParam::Handling(h) } |
- generic_param => { |g| DispositionParam::Generic(g) }));
-
-named!(content_disposition_header<(DispositionType, Vec<DispositionParam>)>, preceded!(
- terminated!(tag!(b"Content-Disposition"), hcolon),
- tuple!(
- disp_type,
- many0!(preceded!(
- tag!(b";"),
- disp_param)))));
-
-named!(content_encoding_header<Vec<ContentCoding>>, preceded!(
- terminated!(alt!(tag!(b"Content-Encoding") | tag!(b"e")), hcolon),
- separated_nonempty_list!(
- tag!(b","),
- token)));
-
-named!(content_language_header<Vec<LanguageTag>>, preceded!(
- terminated!(tag!(b"Content-Language"), hcolon),
- separated_nonempty_list!(
- tag!(b","),
- language_tag)));
-
-named!(content_length_header<u32>, preceded!(
- terminated!(alt!(tag!(b"Content-Length") | tag!(b"l")), hcolon),
- number));
-
-named!(content_type_header<MediaType>, 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<Day>, 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<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<Date>, tuple!(
- terminated!(number, tag!(b" ")),
- terminated!(month, tag!(b" ")),
- number));
-
-named!(time<Time>, tuple!(
- terminated!(number, tag!(b":")),
- terminated!(number, tag!(b":")),
- number));
-
-named!(date_time<DateTime>, tuple!(
- terminated!(wkday, tag!(b", ")),
- terminated!(date, tag!(b" ")),
- terminated!(time, tag!(b" GMT"))));
-
-named!(date_header<DateTime>, preceded!(
- terminated!(tag!(b"Date"), hcolon),
- date_time));
-
-named!(error_uri<ErrorUri>, tuple!(
- delimited!(
- tag!(b"<"),
- absolute_uri,
- tag!(b">")
- ),
- many0!(preceded!(
- tag!(b";"),
- generic_param))));
-
-named!(error_info_header<Vec<ErrorUri>>, preceded!(
- terminated!(tag!(b"Error-Info"), hcolon),
- separated_nonempty_list!(
- tag!(","),
- error_uri)));
-
-named!(expires_header<u32>, preceded!(
- terminated!(tag!(b"Expires"), hcolon),
- number));
-
-named!(from_param<FromParam>, alt!(
- preceded!(tag!("tag="), token) => { |t| FromParam::Tag(t) } |
- generic_param => { |g| FromParam::Generic(g) }));
-
-named!(from_header<From>, preceded!(
- terminated!(alt!(tag!(b"From") | tag!("f")), hcolon),
- tuple!(
- target,
- many0!(preceded!(
- tag!(b";"),
- from_param)))));
-
-named!(in_reply_to_header<Vec<CallId>>, preceded!(
- terminated!(tag!(b"In-Reply-To"), hcolon),
- separated_nonempty_list!(
- tag!(","),
- call_id)));
-
-named!(max_forwards_header<u32>, preceded!(
- terminated!(tag!(b"Max-Forwards"), hcolon),
- number));
-
-named!(mime_version_header<(u32, u32)>, preceded!(
- terminated!(tag!(b"MIME-Version"), hcolon),
- separated_pair!(
- number,
- tag!(b"."),
- number)));
-
-named!(min_expires_header<u32>, preceded!(
- terminated!(tag!(b"Min-Expires"), hcolon),
- number));
-
-named!(organization_header<Vec<u8>>, preceded!(
- terminated!(tag!(b"Organization"), hcolon),
- word));
-
-named!(priority_header<Priority>, preceded!(
- terminated!(tag!(b"Priority"), hcolon),
- alt!(
- tag!(b"emergency") => { |_| Priority::Emergency } |
- tag!(b"urgent") => { |_| Priority::Urgent } |
- tag!(b"normal") => { |_| Priority::Normal } |
- tag!(b"non-urgent") => { |_| Priority::NonUrgent } |
- token => { |t| Priority::Other(t) })));
-
-named!(domain<Vec<Domain>>, delimited!(
- tag!(b"domain=\""),
- separated_nonempty_list!(
- tag!(" "),
- alt!(
- absolute_uri => { |u| Domain::Uri(u) } |
- abs_path => { |p| Domain::Path(p) }
- )),
- tag!(b"\"")));
-
-named!(boolean<bool>, alt!(
- tag!(b"true") => { |_| true } |
- tag!(b"false") => { |_| false }));
-
-named!(stale<bool>, preceded!(
- tag!(b"stale="),
- boolean));
-
-named!(qop_options<Vec<Qop>>, delimited!(
- tag!(b"qop=\""),
- separated_nonempty_list!(
- tag!(b","),
- qop_value),
- tag!(b"\"")));
-
-named!(digest_challenge<Vec<DigestChallenge>>, many1!(alt!(
- realm => { |r| DigestChallenge::Realm(r) } |
- domain => { |d| DigestChallenge::Domain(d) } |
- nonce => { |n| DigestChallenge::Nonce(n) } |
- opaque => { |o| DigestChallenge::Opaque(o) } |
- stale => { |s| DigestChallenge::Stale(s) } |
- qop_options => { |q| DigestChallenge::QopOptions(q) } |
- auth_param => { |(k, v)| DigestChallenge::AuthParam(k, v) })));
-
-use self::other_response as other_challenge;
-
-named!(challenge<Challenge>, alt!(
- preceded!(tag!(b"Digest "), digest_challenge) => { |d| Challenge::Digest(d) } |
- other_challenge => { |(s, p)| Challenge::Other(s, p) }));
-
-named!(proxy_authenticate_header<Challenge>, preceded!(
- terminated!(tag!(b"Proxy-Authenticate"), hcolon),
- challenge));
-
-named!(proxy_authorization_header<Credentials>, preceded!(
- terminated!(tag!(b"Proxy-Authorization"), hcolon),
- credentials));
-
-named!(proxy_require_header<Vec<OptionTag>>, preceded!(
- terminated!(tag!(b"Proxy-Require"), hcolon),
- separated_nonempty_list!(
- tag!(b","),
- token)));
-
-named!(route<Route>, pair!(
- name_addr,
- many0!(preceded!(
- tag!(b";"),
- generic_param))));
-
-named!(record_route_header<Vec<Route>>, preceded!(
- terminated!(tag!(b"Record-Route"), hcolon),
- separated_nonempty_list!(
- tag!(b","),
- route)));
-
-named!(reply_to<ReplyTo>, pair!(
- target,
- many0!(preceded!(
- tag!(b";"),
- generic_param))));
-
-named!(reply_to_header<Vec<ReplyTo>>, preceded!(
- terminated!(tag!(b"Reply-To"), hcolon),
- separated_nonempty_list!(
- tag!(b","),
- reply_to)));
-
-named!(require_header<Vec<OptionTag>>, preceded!(
- terminated!(tag!(b"Require"), hcolon),
- separated_nonempty_list!(
- tag!(b","),
- token)));
-
-named!(retry_after_param<RetryAfterParam>, alt!(
- preceded!(tag!(b"duration="), number) => { |d| RetryAfterParam::Duration(d) } |
- generic_param => { |g| RetryAfterParam::Generic(g) }));
-
-named!(retry_after_header<RetryAfter>, preceded!(
- terminated!(tag!(b"Retry-After"), hcolon),
- pair!(
- number,
- many0!(preceded!(
- tag!(b";"),
- retry_after_param
- )))));
-
-named!(route_header<Vec<Route>>, preceded!(
- terminated!(tag!(b"Route"), hcolon),
- separated_nonempty_list!(
- tag!(b","),
- route)));
-
-named!(server<Server>, pair!(
- token,
- opt!(preceded!(
- tag!(b"/"),
- token))));
-
-named!(server_header<Vec<Server>>, preceded!(
- terminated!(tag!(b"Server"), hcolon),
- separated_nonempty_list!(
- tag!(b" "),
- server)));
-
-named!(subject_header<Vec<u8>>, preceded!(
- terminated!(alt!(tag!(b"Subject") | tag!(b"s")), hcolon),
- word));
-
-named!(supported_header<Vec<OptionTag>>, preceded!(
- terminated!(alt!(tag!(b"Supported") | tag!(b"k")), hcolon),
- separated_nonempty_list!(
- tag!(b","),
- token)));
-
-use self::float as delay;
-
-named!(timestamp_header<Vec<f32>>, preceded!(
- terminated!(tag!(b"Timestamp"), hcolon),
- separated_nonempty_list!(
- tag!(b" "),
- delay)));
-
-named!(to_param<ToParam>, alt!(
- preceded!(tag!("tag="), token) => { |t| ToParam::Tag(t) } |
- generic_param => { |g| ToParam::Generic(g) }));
-
-named!(to_header<To>, preceded!(
- terminated!(alt!(tag!(b"To") | tag!("t")), hcolon),
- tuple!(
- target,
- many0!(preceded!(
- tag!(b";"),
- to_param)))));
-
-named!(unsupported_header<Vec<OptionTag>>, preceded!(
- terminated!(tag!(b"Unsupported"), hcolon),
- separated_nonempty_list!(
- tag!(b","),
- token)));
-
-named!(user_agent_header<Vec<Server>>, preceded!(
- terminated!(tag!(b"User-Agent"), hcolon),
- separated_nonempty_list!(
- tag!(b" "),
- server)));
-
-named!(protocol_name<Protocol>, alt!(
- tag!(b"SIP") => { |_| Protocol::SIP } |
- token => { |t| Protocol::Other(t) }
-));
-
-named!(transport<Transport>, alt!(
- tag!(b"UDP") => { |_| Transport::Udp } |
- tag!(b"TCP") => { |_| Transport::Tcp } |
- tag!(b"TLS") => { |_| Transport::Tls } |
- tag!(b"SCTP") => { |_| Transport::Sctp } |
- token => { |t| Transport::Other(t) }));
-
-named!(sent_protocol<SentProtocol>, tuple!(
- terminated!(protocol_name, tag!("/")),
- terminated!(token, tag!("/")),
- transport));
-
-use self::hostport as sent_by;
-
-named!(received<Received>, alt!(
- ipv4_address => { |(a, b, c, d)| Received::Ipv4Address(a,b,c,d) } |
- ipv6_address => { |i| Received::Ipv6Address(i) }
-));
-
-named!(via_param<ViaParam>, alt!(
- preceded!(tag!(b"ttl="), number) => { |t| ViaParam::Ttl(t) } |
- preceded!(tag!(b"maddr="), host) => { |h| ViaParam::Maddr(h) } |
- preceded!(tag!(b"received="), received) => { |r| ViaParam::Received(r) } |
- preceded!(tag!(b"branch="), token) => { |t| ViaParam::Branch(t) } |
- generic_param => { |g| ViaParam::Extension(g) }
-));
-
-named!(via<Via>, tuple!(
- terminated!(sent_protocol, tag!(b" ")),
- sent_by,
- many0!(preceded!(
- tag!(b";"),
- via_param))));
-
-named!(via_header<Vec<Via>>, preceded!(
- terminated!(alt!(tag!(b"Via") | tag!(b"v")), hcolon),
- separated_nonempty_list!(
- tag!(b","),
- via)));
-
-named!(warning_agent<WarningAgent>, alt!(
- hostport => { |h| WarningAgent::Host(h) } |
- token => { |p| WarningAgent::Pseudonym(p) }));
-
-named!(warning<Warning>, tuple!(
- terminated!(number, tag!(b" ")),
- terminated!(warning_agent, tag!(b" ")),
- quoted_string));
-
-named!(warning_header<Vec<Warning>>, preceded!(
- terminated!(tag!(b"Warning"), hcolon),
- separated_nonempty_list!(
- tag!(b","),
- warning)));
-
-named!(www_authenticate_header<Challenge>, preceded!(
- terminated!(tag!(b"WWW-Authenticate"), hcolon),
- challenge));
-
-named!(extension_header<(Vec<u8>, Vec<u8>)>, separated_pair!(
- token,
- hcolon,
- word));
-
-named!(pub header<Header>, alt!(
-// RFC 3261 Headers
- accept_header => { |a| Header::Accept(a) } |
- accept_encoding_header => { |a| Header::AcceptEncoding(a) } |
- accept_language_header => { |a| Header::AcceptLanguage(a) } |
- alert_info_header => { |a| Header::AlertInfo(a) } |
- allow_header => { |a| Header::Allow(a) } |
- authentication_info_header => { |a| Header::AuthenticationInfo(a) } |
- authorization_header => { |a| Header::Authorization(a) } |
- call_id_header => { |c| Header::CallId(c) } |
- call_info_header => { |c| Header::CallInfo(c) } |
- contact_header => { |c| Header::Contact(c) } |
- content_disposition_header => { |(t, p)| Header::ContentDisposition(t, p) } |
- content_encoding_header => { |e| Header::ContentEncoding(e) } |
- content_language_header => { |l| Header::ContentLanguage(l) } |
- content_length_header => { |l| Header::ContentLength(l) } |
- content_type_header => { |t| Header::ContentType(t) } |
- cseq_header => { |(c, m)| Header::CSeq(c, m) } |
- date_header => { |d| Header::Date(d) } |
- error_info_header => { |e| Header::ErrorInfo(e) } |
- expires_header => { |e| Header::Expires(e) } |
- from_header => { |f| Header::From(f) } |
- in_reply_to_header => { |i| Header::InReplyTo(i) } |
- max_forwards_header => { |m| Header::MaxForwards(m) } |
- mime_version_header => { |(m, v)| Header::MimeVersion(m, v) } |
- min_expires_header => { |m| Header::MinExpires(m) } |
- organization_header => { |o| Header::Organization(o) } |
- priority_header => { |p| Header::Priority(p) } |
- proxy_authenticate_header => { |p| Header::ProxyAuthenticate(p) } |
- proxy_authorization_header => { |p| Header::ProxyAuthorization(p) } |
- proxy_require_header => { |p| Header::ProxyRequire(p) } |
- record_route_header => { |r| Header::RecordRoute(r) } |
- reply_to_header => { |r| Header::ReplyTo(r) } |
- require_header => { |r| Header::Require(r) } |
- retry_after_header => { |r| Header::RetryAfter(r) } |
- route_header => { |r| Header::Route(r) } |
- server_header => { |s| Header::Server(s) } |
- subject_header => { |s| Header::Subject(s) } |
- supported_header => { |s| Header::Supported(s) } |
- timestamp_header => { |t| Header::Timestamp(t) } |
- to_header => { |t| Header::To(t) } |
- unsupported_header => { |u| Header::Unsupported(u) } |
- user_agent_header => { |u| Header::UserAgent(u) } |
- via_header => { |v| Header::Via(v) } |
- warning_header => { |w| Header::Warning(w) } |
- www_authenticate_header => { |w| Header::WwwAuthenticate(w) } |
-// Custom extension headers
- extension_header => { |(n, v)| Header::Extension { name: n, value: v } }
-));
--- /dev/null
+use parser::*;
+
+/// Headers
+
+// Accept Header
+
+named!(media_main_type<MediaMainType>, 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;
+
+named!(media_value<Vec<u8>>, alt!(
+ token |
+ quoted_string));
+
+named!(media_parameter<MediaParameter>, separated_pair!(
+ media_attribute,
+ tag!(b"="),
+ media_value));
+
+named!(media_type<MediaType>, separated_pair!(
+ media_main_type,
+ tag!(b"/"),
+ media_subtype));
+
+named!(media_range<MediaRange>, 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<GenericParam>, separated_pair!(
+ token,
+ tag!(b"="),
+ opt!(token)));
+
+use self::float as qvalue;
+
+named!(qparam<f32>, preceded!(tag!(b"q="), qvalue));
+
+named!(accept_param<AcceptParam>, alt!(
+ qparam => { |x| AcceptParam::Qvalue(x) } |
+ generic_param => { |x| AcceptParam::Generic(x) }));
+
+named!(accept_range<AcceptRange>, tuple!(
+ media_range,
+ many0!(preceded!(
+ tag!(b";"),
+ accept_param))));
+
+named!(accept_header<Vec<AcceptRange>>, preceded!(
+ terminated!(tag!(b"Accept"), hcolon),
+ separated_nonempty_list!(
+ tag!(b","),
+ accept_range)));
+
+named!(codings<Coding>, alt!(
+ tag!(b"*") => { |_| Coding::All } |
+ token => { |t| Coding::Content(t) }
+));
+
+named!(encoding<Encoding>, tuple!(
+ codings,
+ many0!(preceded!(
+ tag!(b";"),
+ accept_param))));
+
+named!(accept_encoding_header<Vec<Encoding>>, preceded!(
+ terminated!(tag!(b"Accept-Encoding"), hcolon),
+ separated_nonempty_list!(
+ tag!(b","),
+ encoding)));
+
+named!(language_token<Vec<u8>>, many1!(alpha));
+
+named!(language_tag<LanguageTag>, separated_nonempty_list!(
+ tag!(b"-"),
+ language_token));
+
+named!(language_range<LanguageRange>, alt!(
+ tag!(b"*") => { |_| LanguageRange::All } |
+ language_tag => { |x : LanguageTag| LanguageRange::Range(x) }));
+
+named!(language<Language>, tuple!(
+ language_range,
+ many0!(preceded!(
+ tag!(b";"),
+ accept_param))));
+
+named!(accept_language_header<Vec<Language>>, preceded!(
+ terminated!(tag!(b"Accept-Language"), hcolon),
+ separated_nonempty_list!(
+ tag!(b","),
+ language)));
+
+named!(alert_param<AlertParam>, tuple!(
+ delimited!(
+ tag!(b"<"),
+ absolute_uri,
+ tag!(b">")
+ ),
+ many0!(generic_param)));
+
+named!(alert_info_header<Vec<AlertParam>>, preceded!(
+ terminated!(tag!(b"Alert-Info"), hcolon),
+ separated_nonempty_list!(
+ tag!(b","),
+ alert_param)));
+
+named!(allow_header<Vec<Method>>, preceded!(
+ terminated!(tag!(b"Allow"), hcolon),
+ separated_nonempty_list!(
+ tag!(b","),
+ method)));
+
+named!(nextnonce<Vec<u8>>, preceded!(
+ tag!(b"nc="),
+ quoted_string));
+
+named!(qop_value<Qop>, alt!(
+ tag!(b"auth") => { |x| Qop::Auth } |
+ tag!(b"auth-init") => { |x| Qop::AuthInit } |
+ token => { |x| Qop::Token(x) }));
+
+named!(message_qop<Qop>, preceded!(
+ tag!(b"qop="),
+ qop_value));
+
+named!(response_digest<Vec<u8>>, delimited!(
+ tag!(b"\""),
+ many0!(hex),
+ tag!(b"\"")));
+
+named!(response_auth<Vec<u8>>, preceded!(
+ tag!(b"rspauth="),
+ response_digest));
+
+named!(cnonce<Vec<u8>>, preceded!(
+ tag!(b"cnonce="),
+ quoted_string));
+
+named!(nc_value<Vec<u8>>, many1!(lhex));
+
+named!(nonce_count<Vec<u8>>, preceded!(
+ tag!(b"nc="),
+ nc_value));
+
+named!(ainfo<AuthenticationInfo>, 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<Vec<AuthenticationInfo>>, preceded!(
+ terminated!(tag!(b"Authentication-Info"), hcolon),
+ separated_nonempty_list!(
+ tag!(b","),
+ ainfo)));
+
+named!(username<Vec<u8>>, preceded!(
+ tag!(b"username="),
+ quoted_string));
+
+named!(realm<Vec<u8>>, preceded!(
+ tag!(b"realm="),
+ quoted_string));
+
+named!(nonce<Vec<u8>>, preceded!(
+ tag!(b"nonce="),
+ quoted_string));
+
+named!(digest_uri<Vec<u8>>, preceded!(
+ tag!(b"digest_uri="),
+ quoted_string));
+
+named!(dresponse<Vec<u8>>, preceded!(
+ tag!(b"response="),
+ response_digest));
+
+named!(algorithm<Algorithm>, alt!(
+ tag!("MD5") => { |_| Algorithm::Md5 } |
+ tag!("MD5-sess") => { |_| Algorithm::Md5Session } |
+ token => { |t| Algorithm::Token(t) }
+));
+
+named!(opaque<Vec<u8>>, preceded!(
+ tag!(b"opaque="),
+ quoted_string));
+
+named!(auth_param<AuthParam>, separated_pair!(
+ token,
+ tag!(b"="),
+ alt!(
+ token |
+ quoted_string)));
+
+named!(digest_response<Vec<DigestResponse>>, 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<u8>, Vec<AuthParam>)>, separated_pair!(
+ token,
+ tag!(b" "),
+ separated_nonempty_list!(
+ tag!(b","),
+ auth_param)));
+
+named!(credentials<Credentials>, alt!(
+ preceded!(
+ tag!(b"Digest "),
+ digest_response) => { |d| Credentials::Digest(d) } |
+ other_response => { |(s,p)| Credentials::Other(s, p) }));
+
+named!(authorization_header<Credentials>, preceded!(
+ terminated!(tag!(b"Authorization"), hcolon),
+ credentials));
+
+named!(call_id<CallId>, tuple!(
+ word,
+ opt!(preceded!(
+ tag!(b"@"),
+ word))));
+
+named!(call_id_header<CallId>, preceded!(
+ terminated!(alt!(tag!(b"Call-ID") | tag!(b"i")), hcolon),
+ call_id));
+
+named!(purpose<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<InfoParam>, alt!(
+ preceded!(
+ tag!(b"purpose="),
+ purpose) => { |p| InfoParam::Purpose(p) } |
+ generic_param => { |g| InfoParam::Generic(g) }));
+
+named!(info<Info>, tuple!(
+ delimited!(
+ tag!(b"<"),
+ absolute_uri,
+ tag!(b">")
+ ),
+ many0!(preceded!(
+ tag!(b";"),
+ info_param))));
+
+named!(call_info_header<Vec<Info>>, preceded!(
+ terminated!(tag!(b"Call-Info"), hcolon),
+ separated_nonempty_list!(
+ tag!(","),
+ info)));
+
+named!(display_name<Vec<u8>>, alt!(
+ token |
+ quoted_string));
+
+named!(name_addr<NameAddr>, tuple!(
+ opt!(display_name),
+ delimited!(
+ tag!(b"<"),
+ uri,
+ tag!(b">"))));
+
+named!(expires<u32>, preceded!(
+ tag!(b"expires="),
+ number));
+
+named!(contact_param<ContactParam>, alt!(
+ qparam => {|q| ContactParam::Qvalue(q) } |
+ expires => {|e| ContactParam::Expires(e) } |
+ generic_param => {|g| ContactParam::Generic(g) }));
+
+named!(target<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<ContactParam>)>, tuple!(
+ target,
+ many0!(preceded!(
+ tag!(b";"),
+ contact_param
+ ))));
+
+named!(contact_header<Contact>, 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<DispositionType>, 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<Handling>, alt!(
+ tag!(b"optional") => { |_| Handling::Optional } |
+ tag!(b"required") => { |_| Handling::Required } |
+ token => { |t| Handling::Token(t) }));
+
+named!(disp_param<DispositionParam>, alt!(
+ preceded!(tag!(b"handling="), handling) => { |h| DispositionParam::Handling(h) } |
+ generic_param => { |g| DispositionParam::Generic(g) }));
+
+named!(content_disposition_header<(DispositionType, Vec<DispositionParam>)>, preceded!(
+ terminated!(tag!(b"Content-Disposition"), hcolon),
+ tuple!(
+ disp_type,
+ many0!(preceded!(
+ tag!(b";"),
+ disp_param)))));
+
+named!(content_encoding_header<Vec<ContentCoding>>, preceded!(
+ terminated!(alt!(tag!(b"Content-Encoding") | tag!(b"e")), hcolon),
+ separated_nonempty_list!(
+ tag!(b","),
+ token)));
+
+named!(content_language_header<Vec<LanguageTag>>, preceded!(
+ terminated!(tag!(b"Content-Language"), hcolon),
+ separated_nonempty_list!(
+ tag!(b","),
+ language_tag)));
+
+named!(content_length_header<u32>, preceded!(
+ terminated!(alt!(tag!(b"Content-Length") | tag!(b"l")), hcolon),
+ number));
+
+named!(content_type_header<MediaType>, 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<Day>, 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<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<Date>, tuple!(
+ terminated!(number, tag!(b" ")),
+ terminated!(month, tag!(b" ")),
+ number));
+
+named!(time<Time>, tuple!(
+ terminated!(number, tag!(b":")),
+ terminated!(number, tag!(b":")),
+ number));
+
+named!(date_time<DateTime>, tuple!(
+ terminated!(wkday, tag!(b", ")),
+ terminated!(date, tag!(b" ")),
+ terminated!(time, tag!(b" GMT"))));
+
+named!(date_header<DateTime>, preceded!(
+ terminated!(tag!(b"Date"), hcolon),
+ date_time));
+
+named!(error_uri<ErrorUri>, tuple!(
+ delimited!(
+ tag!(b"<"),
+ absolute_uri,
+ tag!(b">")
+ ),
+ many0!(preceded!(
+ tag!(b";"),
+ generic_param))));
+
+named!(error_info_header<Vec<ErrorUri>>, preceded!(
+ terminated!(tag!(b"Error-Info"), hcolon),
+ separated_nonempty_list!(
+ tag!(","),
+ error_uri)));
+
+named!(expires_header<u32>, preceded!(
+ terminated!(tag!(b"Expires"), hcolon),
+ number));
+
+named!(from_param<FromParam>, alt!(
+ preceded!(tag!("tag="), token) => { |t| FromParam::Tag(t) } |
+ generic_param => { |g| FromParam::Generic(g) }));
+
+named!(from_header<From>, preceded!(
+ terminated!(alt!(tag!(b"From") | tag!("f")), hcolon),
+ tuple!(
+ target,
+ many0!(preceded!(
+ tag!(b";"),
+ from_param)))));
+
+named!(in_reply_to_header<Vec<CallId>>, preceded!(
+ terminated!(tag!(b"In-Reply-To"), hcolon),
+ separated_nonempty_list!(
+ tag!(","),
+ call_id)));
+
+named!(max_forwards_header<u32>, preceded!(
+ terminated!(tag!(b"Max-Forwards"), hcolon),
+ number));
+
+named!(mime_version_header<(u32, u32)>, preceded!(
+ terminated!(tag!(b"MIME-Version"), hcolon),
+ separated_pair!(
+ number,
+ tag!(b"."),
+ number)));
+
+named!(min_expires_header<u32>, preceded!(
+ terminated!(tag!(b"Min-Expires"), hcolon),
+ number));
+
+named!(organization_header<Vec<u8>>, preceded!(
+ terminated!(tag!(b"Organization"), hcolon),
+ word));
+
+named!(priority_header<Priority>, preceded!(
+ terminated!(tag!(b"Priority"), hcolon),
+ alt!(
+ tag!(b"emergency") => { |_| Priority::Emergency } |
+ tag!(b"urgent") => { |_| Priority::Urgent } |
+ tag!(b"normal") => { |_| Priority::Normal } |
+ tag!(b"non-urgent") => { |_| Priority::NonUrgent } |
+ token => { |t| Priority::Other(t) })));
+
+named!(domain<Vec<Domain>>, delimited!(
+ tag!(b"domain=\""),
+ separated_nonempty_list!(
+ tag!(" "),
+ alt!(
+ absolute_uri => { |u| Domain::Uri(u) } |
+ abs_path => { |p| Domain::Path(p) }
+ )),
+ tag!(b"\"")));
+
+named!(boolean<bool>, alt!(
+ tag!(b"true") => { |_| true } |
+ tag!(b"false") => { |_| false }));
+
+named!(stale<bool>, preceded!(
+ tag!(b"stale="),
+ boolean));
+
+named!(qop_options<Vec<Qop>>, delimited!(
+ tag!(b"qop=\""),
+ separated_nonempty_list!(
+ tag!(b","),
+ qop_value),
+ tag!(b"\"")));
+
+named!(digest_challenge<Vec<DigestChallenge>>, many1!(alt!(
+ realm => { |r| DigestChallenge::Realm(r) } |
+ domain => { |d| DigestChallenge::Domain(d) } |
+ nonce => { |n| DigestChallenge::Nonce(n) } |
+ opaque => { |o| DigestChallenge::Opaque(o) } |
+ stale => { |s| DigestChallenge::Stale(s) } |
+ qop_options => { |q| DigestChallenge::QopOptions(q) } |
+ auth_param => { |(k, v)| DigestChallenge::AuthParam(k, v) })));
+
+use self::other_response as other_challenge;
+
+named!(challenge<Challenge>, alt!(
+ preceded!(tag!(b"Digest "), digest_challenge) => { |d| Challenge::Digest(d) } |
+ other_challenge => { |(s, p)| Challenge::Other(s, p) }));
+
+named!(proxy_authenticate_header<Challenge>, preceded!(
+ terminated!(tag!(b"Proxy-Authenticate"), hcolon),
+ challenge));
+
+named!(proxy_authorization_header<Credentials>, preceded!(
+ terminated!(tag!(b"Proxy-Authorization"), hcolon),
+ credentials));
+
+named!(proxy_require_header<Vec<OptionTag>>, preceded!(
+ terminated!(tag!(b"Proxy-Require"), hcolon),
+ separated_nonempty_list!(
+ tag!(b","),
+ token)));
+
+named!(route<Route>, pair!(
+ name_addr,
+ many0!(preceded!(
+ tag!(b";"),
+ generic_param))));
+
+named!(record_route_header<Vec<Route>>, preceded!(
+ terminated!(tag!(b"Record-Route"), hcolon),
+ separated_nonempty_list!(
+ tag!(b","),
+ route)));
+
+named!(reply_to<ReplyTo>, pair!(
+ target,
+ many0!(preceded!(
+ tag!(b";"),
+ generic_param))));
+
+named!(reply_to_header<Vec<ReplyTo>>, preceded!(
+ terminated!(tag!(b"Reply-To"), hcolon),
+ separated_nonempty_list!(
+ tag!(b","),
+ reply_to)));
+
+named!(require_header<Vec<OptionTag>>, preceded!(
+ terminated!(tag!(b"Require"), hcolon),
+ separated_nonempty_list!(
+ tag!(b","),
+ token)));
+
+named!(retry_after_param<RetryAfterParam>, alt!(
+ preceded!(tag!(b"duration="), number) => { |d| RetryAfterParam::Duration(d) } |
+ generic_param => { |g| RetryAfterParam::Generic(g) }));
+
+named!(retry_after_header<RetryAfter>, preceded!(
+ terminated!(tag!(b"Retry-After"), hcolon),
+ pair!(
+ number,
+ many0!(preceded!(
+ tag!(b";"),
+ retry_after_param
+ )))));
+
+named!(route_header<Vec<Route>>, preceded!(
+ terminated!(tag!(b"Route"), hcolon),
+ separated_nonempty_list!(
+ tag!(b","),
+ route)));
+
+named!(server<Server>, pair!(
+ token,
+ opt!(preceded!(
+ tag!(b"/"),
+ token))));
+
+named!(server_header<Vec<Server>>, preceded!(
+ terminated!(tag!(b"Server"), hcolon),
+ separated_nonempty_list!(
+ tag!(b" "),
+ server)));
+
+named!(subject_header<Vec<u8>>, preceded!(
+ terminated!(alt!(tag!(b"Subject") | tag!(b"s")), hcolon),
+ word));
+
+named!(supported_header<Vec<OptionTag>>, preceded!(
+ terminated!(alt!(tag!(b"Supported") | tag!(b"k")), hcolon),
+ separated_nonempty_list!(
+ tag!(b","),
+ token)));
+
+use self::float as delay;
+
+named!(timestamp_header<Vec<f32>>, preceded!(
+ terminated!(tag!(b"Timestamp"), hcolon),
+ separated_nonempty_list!(
+ tag!(b" "),
+ delay)));
+
+named!(to_param<ToParam>, alt!(
+ preceded!(tag!("tag="), token) => { |t| ToParam::Tag(t) } |
+ generic_param => { |g| ToParam::Generic(g) }));
+
+named!(to_header<To>, preceded!(
+ terminated!(alt!(tag!(b"To") | tag!("t")), hcolon),
+ tuple!(
+ target,
+ many0!(preceded!(
+ tag!(b";"),
+ to_param)))));
+
+named!(unsupported_header<Vec<OptionTag>>, preceded!(
+ terminated!(tag!(b"Unsupported"), hcolon),
+ separated_nonempty_list!(
+ tag!(b","),
+ token)));
+
+named!(user_agent_header<Vec<Server>>, preceded!(
+ terminated!(tag!(b"User-Agent"), hcolon),
+ separated_nonempty_list!(
+ tag!(b" "),
+ server)));
+
+named!(protocol_name<Protocol>, alt!(
+ tag!(b"SIP") => { |_| Protocol::SIP } |
+ token => { |t| Protocol::Other(t) }
+));
+
+named!(transport<Transport>, alt!(
+ tag!(b"UDP") => { |_| Transport::Udp } |
+ tag!(b"TCP") => { |_| Transport::Tcp } |
+ tag!(b"TLS") => { |_| Transport::Tls } |
+ tag!(b"SCTP") => { |_| Transport::Sctp } |
+ token => { |t| Transport::Other(t) }));
+
+named!(sent_protocol<SentProtocol>, tuple!(
+ terminated!(protocol_name, tag!("/")),
+ terminated!(token, tag!("/")),
+ transport));
+
+use self::hostport as sent_by;
+
+named!(received<Received>, alt!(
+ ipv4_address => { |(a, b, c, d)| Received::Ipv4Address(a,b,c,d) } |
+ ipv6_address => { |i| Received::Ipv6Address(i) }
+));
+
+named!(via_param<ViaParam>, alt!(
+ preceded!(tag!(b"ttl="), number) => { |t| ViaParam::Ttl(t) } |
+ preceded!(tag!(b"maddr="), host) => { |h| ViaParam::Maddr(h) } |
+ preceded!(tag!(b"received="), received) => { |r| ViaParam::Received(r) } |
+ preceded!(tag!(b"branch="), token) => { |t| ViaParam::Branch(t) } |
+ generic_param => { |g| ViaParam::Extension(g) }
+));
+
+named!(via<Via>, tuple!(
+ terminated!(sent_protocol, tag!(b" ")),
+ sent_by,
+ many0!(preceded!(
+ tag!(b";"),
+ via_param))));
+
+named!(via_header<Vec<Via>>, preceded!(
+ terminated!(alt!(tag!(b"Via") | tag!(b"v")), hcolon),
+ separated_nonempty_list!(
+ tag!(b","),
+ via)));
+
+named!(warning_agent<WarningAgent>, alt!(
+ hostport => { |h| WarningAgent::Host(h) } |
+ token => { |p| WarningAgent::Pseudonym(p) }));
+
+named!(warning<Warning>, tuple!(
+ terminated!(number, tag!(b" ")),
+ terminated!(warning_agent, tag!(b" ")),
+ quoted_string));
+
+named!(warning_header<Vec<Warning>>, preceded!(
+ terminated!(tag!(b"Warning"), hcolon),
+ separated_nonempty_list!(
+ tag!(b","),
+ warning)));
+
+named!(www_authenticate_header<Challenge>, preceded!(
+ terminated!(tag!(b"WWW-Authenticate"), hcolon),
+ challenge));
+
+named!(extension_header<(Vec<u8>, Vec<u8>)>, separated_pair!(
+ token,
+ hcolon,
+ word));
+
+named!(pub header<Header>, alt!(
+// RFC 3261 Headers
+ accept_header => { |a| Header::Accept(a) } |
+ accept_encoding_header => { |a| Header::AcceptEncoding(a) } |
+ accept_language_header => { |a| Header::AcceptLanguage(a) } |
+ alert_info_header => { |a| Header::AlertInfo(a) } |
+ allow_header => { |a| Header::Allow(a) } |
+ authentication_info_header => { |a| Header::AuthenticationInfo(a) } |
+ authorization_header => { |a| Header::Authorization(a) } |
+ call_id_header => { |c| Header::CallId(c) } |
+ call_info_header => { |c| Header::CallInfo(c) } |
+ contact_header => { |c| Header::Contact(c) } |
+ content_disposition_header => { |(t, p)| Header::ContentDisposition(t, p) } |
+ content_encoding_header => { |e| Header::ContentEncoding(e) } |
+ content_language_header => { |l| Header::ContentLanguage(l) } |
+ content_length_header => { |l| Header::ContentLength(l) } |
+ content_type_header => { |t| Header::ContentType(t) } |
+ cseq_header => { |(c, m)| Header::CSeq(c, m) } |
+ date_header => { |d| Header::Date(d) } |
+ error_info_header => { |e| Header::ErrorInfo(e) } |
+ expires_header => { |e| Header::Expires(e) } |
+ from_header => { |f| Header::From(f) } |
+ in_reply_to_header => { |i| Header::InReplyTo(i) } |
+ max_forwards_header => { |m| Header::MaxForwards(m) } |
+ mime_version_header => { |(m, v)| Header::MimeVersion(m, v) } |
+ min_expires_header => { |m| Header::MinExpires(m) } |
+ organization_header => { |o| Header::Organization(o) } |
+ priority_header => { |p| Header::Priority(p) } |
+ proxy_authenticate_header => { |p| Header::ProxyAuthenticate(p) } |
+ proxy_authorization_header => { |p| Header::ProxyAuthorization(p) } |
+ proxy_require_header => { |p| Header::ProxyRequire(p) } |
+ record_route_header => { |r| Header::RecordRoute(r) } |
+ reply_to_header => { |r| Header::ReplyTo(r) } |
+ require_header => { |r| Header::Require(r) } |
+ retry_after_header => { |r| Header::RetryAfter(r) } |
+ route_header => { |r| Header::Route(r) } |
+ server_header => { |s| Header::Server(s) } |
+ subject_header => { |s| Header::Subject(s) } |
+ supported_header => { |s| Header::Supported(s) } |
+ timestamp_header => { |t| Header::Timestamp(t) } |
+ to_header => { |t| Header::To(t) } |
+ unsupported_header => { |u| Header::Unsupported(u) } |
+ user_agent_header => { |u| Header::UserAgent(u) } |
+ via_header => { |v| Header::Via(v) } |
+ warning_header => { |w| Header::Warning(w) } |
+ www_authenticate_header => { |w| Header::WwwAuthenticate(w) } |
+// Custom extension headers
+ extension_header => { |(n, v)| Header::Extension { name: n, value: v } }
+));
--- /dev/null
+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;
+
+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));
+ );
+);
+
+mod header;
+mod top_line;
+
+pub use parser::header::header;
+pub use parser::top_line::top_line;
+
+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'-'
+}
+
+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<Vec<u8>>, many1!(take_1!(is_token)));
+named!(word<Vec<u8>>, many1!(take_1!(is_word)));
+
+named!(method<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<u8>>, many1!(alt!(
+ user_unreserved |
+ escaped)));
+
+named!(password<&[u8], Vec<u8>>, many1!(alt!(
+ password_unreserved |
+ escaped)));
+
+named!(userinfo<&[u8], (Vec<u8>, Option<Vec<u8>>)>, terminated!(
+ pair!(
+ user,
+ opt!(preceded!(tag!(b":"), password))),
+ tag!(b"@")));
+
+named!(domain_label<&[u8], Vec<u8>>, 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<u8>>, 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<O>(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::<O>() {
+ 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<u8>>, delimited!(
+ tag!(b"["),
+ many1!(take_1!(is_ipv6_char)),
+ tag!(b"]")));
+
+named!(host<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<Transport>, 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<UserParam>, 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<u8>>, many1!(alt!(
+ take_1!(is_param_unreserved) |
+ escaped)));
+
+named!(uri_parameter<UriParameter>, 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<UriParameter>>, 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<u8>>, many1!(alt!(
+ take_1!(is_header_unreserved) |
+ escaped)));
+
+named!(hvalue<&[u8], Vec<u8>>, 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<UserInfo>, HostPort, Vec<UriParameter>, Option<UriHeaders>);
+
+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<UserInfo>, 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<u8>>, 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<UserInfo>, 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<u8>>, 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<AbsolutePath>)>, preceded!(tag!("//"), pair!(
+ authority,
+ opt!(abs_path))));
+
+named!(query<&[u8], Vec<u8>>, many0!(uric));
+
+named!(hier_part<&[u8], (HierarchicalPath, Option<Vec<u8>>)>, 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<u8>)>, 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 } }
+));
+
+fn is_spacetab(c: u8) -> bool {
+ c == b' ' || c == b'\t'
+}
+
+fn is_whitespace(c: u8) -> bool {
+ is_spacetab(c)
+}
+
+named!(spacetab<u8>, take_1!(is_spacetab));
+
+named!(crlf, tag!(b"\r\n"));
+
+named!(lws<(Option<(Vec<u8>, &[u8])>, Vec<u8>)>, pair!(
+ opt!(pair!(many0!(take_1!(is_whitespace)), crlf)),
+ many1!(take_1!(is_whitespace))));
+
+named!(sws<Option<(Option<(Vec<u8>, &[u8])>, Vec<u8>)>>, opt!(lws));
+
+named!(hcolon, delimited!(
+ many0!(spacetab),
+ tag!(b":"),
+ sws));
+
+fn is_qdtext_char(c: u8) -> bool {
+ c == 0x21 || (c >= 0x23 && c <= 0x5b) || (c >= 0x5d && c <= 0x7e)
+}
+
+named!(qdtext<u8>, take_1!(is_qdtext_char));
+
+fn is_qdpair_char(c: u8) -> bool {
+ c <= 0x09 || c == 0x0B || c == 0x0C || (c >= 0x0E && c <= 0x7f)
+}
+
+named!(qdpair<u8>, preceded!(
+ tag!("\\"),
+ take_1!(is_qdpair_char)));
+
+named!(quoted_string<Vec<u8>>, delimited!(
+ tag!(b"\""),
+ many0!(alt!(
+ qdtext |
+ qdpair)),
+ tag!(b"\"")));
--- /dev/null
+use parser::*;
+
+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<Vec<u8>>, many0!(alt!(
+ escaped |
+ take_1!(is_reason_phrase_char))));
+
+named!(status_line<&[u8], (Version, u16, Vec<u8>)>, tuple!(
+ sip_version,
+ delimited!(
+ tag!(" "),
+ number,
+ tag!(" ")
+ ),
+ reason_phrase));
+
+named!(pub top_line<TopLine>, 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
+ })}));