use futures::future;
use futures::{Future, Stream};
-use tokio_core::reactor::Handle;
-use tokio_core::net::TcpListener;
-use tokio_io::codec::{Encoder, Decoder};
-use std::io;
-use std;
use nom;
+use std;
+use std::io;
use std::sync::Arc;
+use tokio_core::net::TcpListener;
+use tokio_core::reactor::Handle;
+use tokio_io::codec::{Decoder, Encoder};
-use types::{RequestLine, StatusLine, TopLine, Header};
-use parser::top_line;
use parser::header;
+use parser::top_line;
+use types::{Header, RequestLine, StatusLine, TopLine};
const SPACE: u8 = b' ';
const TAB: u8 = b'\t';
}
}
-
#[derive(Clone, Debug)]
struct UnparsedLine {
value: BytesMut,
trace!("Gathering CRLF");
if let Some(cr) = search.position(|&b| b == CR) {
-
trace!("Found CR at {}", cr);
total += cr;
trace!("Using line: {:?}", std::str::from_utf8(&line));
- match (&mut self.top_line, chartype(line.first()), &mut self.latest_header) {
+ match (
+ &mut self.top_line,
+ chartype(line.first()),
+ &mut self.latest_header,
+ ) {
// Ignore empty top lines
(&mut None, CharType::Line, _) => {
-
trace!("Ignoring empty top line");
-
}
// Top line beginnning with whitespace - ignore
(&mut None, CharType::Whitespace, _) => {
- trace!("Got top line beginning with whitespace - ignore: {:?}",
- line);
+ trace!(
+ "Got top line beginning with whitespace - ignore: {:?}",
+ line
+ );
}
// Top line with no headers! Discard.
trace!("Got end of headers");
- if let Ok(new_message) = PartialMessage::new(top_line.take()
- .unwrap(),
- &mut self.headers) {
-
+ if let Ok(new_message) =
+ PartialMessage::new(top_line.take().unwrap(), &mut self.headers)
+ {
debug!("Got partial message: {:?}", new_message);
self.headers.clear();
}
}
}
-
}
}
}
impl PartialMessage {
- fn new(top_line: UnparsedLine,
- headers: &mut Vec<UnparsedLine>)
- -> Result<PartialMessage, std::str::Utf8Error> {
+ fn new(
+ top_line: UnparsedLine,
+ headers: &mut Vec<UnparsedLine>,
+ ) -> Result<PartialMessage, std::str::Utf8Error> {
Ok(PartialMessage {
top_line: top_line,
- headers: headers.drain(..).filter_map(|line| Header::parse(line)).collect(),
+ headers: headers
+ .drain(..)
+ .filter_map(|line| Header::parse(line))
+ .collect(),
})
}
fn parse(message: PartialMessage, body: Option<BytesMut>) -> Option<Message> {
match top_line(message.top_line.as_bytes()) {
- nom::IResult::Done(_, TopLine::RequestLine(r)) => {
- Some(Message::Request(Request {
- headers: message.headers,
- request_line: (r, message.top_line.clone()),
- body: body,
- }))
- }
- nom::IResult::Done(_, TopLine::StatusLine(s)) => {
- Some(Message::Response(Response {
- headers: message.headers,
- status_line: (s, message.top_line.clone()),
- body: body,
- }))
- }
+ nom::IResult::Done(_, TopLine::RequestLine(r)) => Some(Message::Request(Request {
+ headers: message.headers,
+ request_line: (r, message.top_line.clone()),
+ body: body,
+ })),
+ nom::IResult::Done(_, TopLine::StatusLine(s)) => Some(Message::Response(Response {
+ headers: message.headers,
+ status_line: (s, message.top_line.clone()),
+ body: body,
+ })),
result => {
warn!("Failed to parse top line: {:?}", result);
None
fn decode(&mut self, buf: &mut BytesMut) -> io::Result<Option<Message>> {
if let Some(_) = self.message {
-
trace!("Gathering body");
let length = self.message.iter().map(|m| m.body_length()).next().unwrap();
if length > buf.len() {
return Ok(None);
- } else if let Some(message) = Message::new_with_body(self.message.take().unwrap(),
- buf.split_to(length)) {
+ } else if let Some(message) =
+ Message::new_with_body(self.message.take().unwrap(), buf.split_to(length))
+ {
return Ok(Some(message));
} else {
warn!("Failed to parse message with no body!");
impl Sip {
pub fn new() -> Sip {
- Sip { listeners: Vec::new() }
+ Sip {
+ listeners: Vec::new(),
+ }
}
pub fn add_listener(&mut self, listener: TcpListener) {
self.listeners.push(listener);
}
- pub fn run<F>(self,
- handle: Handle,
- caller: Arc<Box<F>>)
- -> Box<Future<Item = (), Error = std::io::Error>>
- where F: 'static + Fn(Message) -> Result<(), std::io::Error>
+ pub fn run<F>(
+ self,
+ handle: Handle,
+ caller: Arc<Box<F>>,
+ ) -> Box<Future<Item = (), Error = std::io::Error>>
+ where
+ F: 'static + Fn(Message) -> Result<(), std::io::Error>,
{
-
let mut future: Box<Future<Item = (), Error = std::io::Error>> = Box::new(future::ok(()));
for listener in self.listeners {
-
let handle = handle.clone();
let caller = caller.clone();
// Iterate incoming connections
- future = Box::new(future.join(listener.incoming().for_each(move |(tcp, _)| {
-
- let caller = caller.clone();
+ future = Box::new(
+ future
+ .join(listener.incoming().for_each(move |(tcp, _)| {
+ let caller = caller.clone();
- // Split up the read and write halves
- let decoder = SipCodec::new();
+ // Split up the read and write halves
+ let decoder = SipCodec::new();
- let (_sink, stream) = decoder.framed(tcp).split();
+ let (_sink, stream) = decoder.framed(tcp).split();
- let future = stream.for_each(move |message| caller(message));
+ let future = stream.for_each(move |message| caller(message));
- let future = future.map_err(|err| error!("Error {:?}", err));
+ let future = future.map_err(|err| error!("Error {:?}", err));
- // Spawn the future as a concurrent task
- handle.spawn(future);
+ // Spawn the future as a concurrent task
+ handle.spawn(future);
- Ok(())
- }))
- .map(|_| ()));
+ Ok(())
+ })).map(|_| ()),
+ );
}
future
extern crate env_logger;
- use std::ops::DerefMut;
- use std::sync::Arc;
- use std::sync::Mutex;
- use codec::Sip;
use codec::Message;
+ use codec::Sip;
use futures;
- use futures::Future;
use futures::future::Either;
- use tokio_io::io;
+ use futures::Future;
+ use std::net::Shutdown;
+ use std::ops::DerefMut;
+ use std::sync::Arc;
+ use std::sync::Mutex;
use tokio_core::net::TcpListener;
use tokio_core::net::TcpStream;
use tokio_core::reactor::Core;
- use std::net::Shutdown;
+ use tokio_io::io;
use types::Method;
fn decode_sip_message<S: Into<String>>(message: S) -> Message {
let server = {
let m = m.clone();
- sip.run(core.handle(),
- Arc::new(Box::new(move |message| {
- let mut m = m.lock().unwrap();
- *m = Some(message);
- Ok(())
- })))
+ sip.run(
+ core.handle(),
+ Arc::new(Box::new(move |message| {
+ let mut m = m.lock().unwrap();
+ *m = Some(message);
+ Ok(())
+ })),
+ )
};
// Send a request
// Response
match (res, message.deref_mut()) {
- (Ok(Either::B(((ref _socket, ref _response), _))),
- ref mut message @ &mut Some(_)) => message.take().unwrap(),
+ (
+ Ok(Either::B(((ref _socket, ref _response), _))),
+ ref mut message @ &mut Some(_),
+ ) => message.take().unwrap(),
(Err(Either::A((err, _))), _) => panic!("{:?}", err),
(Err(Either::B((err, _))), _) => panic!("{:?}", err),
(_, &mut None) => panic!("No message received"),
fn test_message_decode() {
env_logger::init().unwrap();
- let message =
- decode_sip_message("MESSAGE sip:test.com SIP/2.0\r\n\
- Accept: text/plain\r\n\
- Accept-Encoding: *\r\n\
- Accept-Language: en-gb\r\n\
- Alert-Info: <http://www.example.com/sounds/moo.wav>\r\n\
- Allow: MESSAGE\r\n\
- Authentication-Info: qop=auth\r\n\
- Authorization: Digest username=\"Alice\"\r\n\
- Call-ID: f81d4fae-7dec-11d0-a765-00a0c91e6bf6@foo.bar.com\r\n\
- Call-Info: <http://wwww.example.com/alice/photo.jpg>; purpose=icon\r\n\
- Contact: *\r\n\
- Content-Disposition: session\r\n\
- Content-Encoding: gzip\r\n\
- Content-Language: en-gb\r\n\
- Content-Length: 0\r\n\
- Content-Type: text/plain\r\n\
- CSeq: 1 MESSAGE\r\n\
- Date: Sat, 13 Nov 2010 23:29:00 GMT\r\n\
- Error-Info: <sip:not-in-service-recording@atlanta.com>\r\n\
- Expires: 30\r\n\
- From: sip:+12125551212@server.phone2net.com; tag=887s\r\n\
- In-Reply-To: 70710@saturn.bell-tel.com,17320@saturn.bell-tel. com\r\n\
- Max-Forwards: 32\r\n\
- MIME-Version:2.0\r\n\
- Min-Expires: 30\r\n\
- Organization: Foobar\r\n\
- Priority: normal\r\n\
- Proxy-Authenticate: Digest realm=\"atlanta.com\"\r\n\
- Proxy-Authorization: Digest username=\"Bob\"\r\n\
- Proxy-Require: foo\r\n\
- Record-Route: <sip:server10.biloxi.com;lr>\r\n\
- Reply-To: <sip:bob@biloxi.com>\r\n\
- Require: baz\r\n\
- Retry-After:18000;duration=3600\r\n\
- Route: <sip:bigbox3.site3.atlanta.com;lr>\r\n\
- Server: rust-sip tokio\r\n\
- Subject: Foobaz\r\n\
- Supported: rec\r\n\
- Timestamp: 1 2\r\n\
- To: <sip:operator@cs.columbia.edu>; tag=287447\r\n\
- Unsupported: 100rel\r\n\
- User-Agent: rust-sip\r\n\
- Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bK776asdhds\r\n\
- Warning: 370 devnull \"Failure\"\r\n\
- WWW-Authenticate: Digest realm=\"biloxi.com\"\r\n\
- X-Extension: test\r\n\r\n");
+ let message = decode_sip_message(
+ "MESSAGE sip:test.com SIP/2.0\r\n\
+ Accept: text/plain\r\n\
+ Accept-Encoding: *\r\n\
+ Accept-Language: en-gb\r\n\
+ Alert-Info: <http://www.example.com/sounds/moo.wav>\r\n\
+ Allow: MESSAGE\r\n\
+ Authentication-Info: qop=auth\r\n\
+ Authorization: Digest username=\"Alice\"\r\n\
+ Call-ID: f81d4fae-7dec-11d0-a765-00a0c91e6bf6@foo.bar.com\r\n\
+ Call-Info: <http://wwww.example.com/alice/photo.jpg>; purpose=icon\r\n\
+ Contact: *\r\n\
+ Content-Disposition: session\r\n\
+ Content-Encoding: gzip\r\n\
+ Content-Language: en-gb\r\n\
+ Content-Length: 0\r\n\
+ Content-Type: text/plain\r\n\
+ CSeq: 1 MESSAGE\r\n\
+ Date: Sat, 13 Nov 2010 23:29:00 GMT\r\n\
+ Error-Info: <sip:not-in-service-recording@atlanta.com>\r\n\
+ Expires: 30\r\n\
+ From: sip:+12125551212@server.phone2net.com; tag=887s\r\n\
+ In-Reply-To: 70710@saturn.bell-tel.com,17320@saturn.bell-tel. com\r\n\
+ Max-Forwards: 32\r\n\
+ MIME-Version:2.0\r\n\
+ Min-Expires: 30\r\n\
+ Organization: Foobar\r\n\
+ Priority: normal\r\n\
+ Proxy-Authenticate: Digest realm=\"atlanta.com\"\r\n\
+ Proxy-Authorization: Digest username=\"Bob\"\r\n\
+ Proxy-Require: foo\r\n\
+ Record-Route: <sip:server10.biloxi.com;lr>\r\n\
+ Reply-To: <sip:bob@biloxi.com>\r\n\
+ Require: baz\r\n\
+ Retry-After:18000;duration=3600\r\n\
+ Route: <sip:bigbox3.site3.atlanta.com;lr>\r\n\
+ Server: rust-sip tokio\r\n\
+ Subject: Foobaz\r\n\
+ Supported: rec\r\n\
+ Timestamp: 1 2\r\n\
+ To: <sip:operator@cs.columbia.edu>; tag=287447\r\n\
+ Unsupported: 100rel\r\n\
+ User-Agent: rust-sip\r\n\
+ Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bK776asdhds\r\n\
+ Warning: 370 devnull \"Failure\"\r\n\
+ WWW-Authenticate: Digest realm=\"biloxi.com\"\r\n\
+ X-Extension: test\r\n\r\n",
+ );
if let Message::Request(request) = message {
assert_eq!(request.request_line.0.method, Method::MESSAGE);
// Accept Header
-named!(media_main_type<MediaMainType>, alt!(
+named!(
+ media_main_type<MediaMainType>,
+ alt!(
// Discrete Types
tag!(b"text") => { |_| MediaMainType::Text } |
tag!(b"image") => { |_| MediaMainType::Image } |
tag!(b"message") => { |_| MediaMainType::Message } |
tag!(b"multipart") => { |_| MediaMainType::Multipart } |
// Extensions
- token => { |x| MediaMainType::Extension(x) }));
+ 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_value<Vec<u8>>, alt!(token | quoted_string));
-named!(media_parameter<MediaParameter>, separated_pair!(
- media_attribute,
- tag!(b"="),
- media_value));
+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_type<MediaType>,
+ separated_pair!(media_main_type, tag!(b"/"), media_subtype)
+);
-named!(media_range<MediaRange>, tuple!(
- alt!(
+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))));
+ many0!(preceded!(tag!(b";"), media_parameter))
+ )
+);
-named!(generic_param<GenericParam>, separated_pair!(
- token,
- tag!(b"="),
- opt!(token)));
+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!(
+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!(
+ 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!(
+ 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_tag<LanguageTag>,
+ separated_nonempty_list!(tag!(b"-"), language_token)
+);
-named!(language_range<LanguageRange>, alt!(
+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!(
+ 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) }));
+ token => { |x| Qop::Token(x) })
+);
-named!(message_qop<Qop>, preceded!(
- tag!(b"qop="),
- qop_value));
+named!(message_qop<Qop>, preceded!(tag!(b"qop="), qop_value));
-named!(response_digest<Vec<u8>>, delimited!(
- tag!(b"\""),
- many0!(hex),
- tag!(b"\"")));
+named!(
+ response_digest<Vec<u8>>,
+ delimited!(tag!(b"\""), many0!(hex), tag!(b"\""))
+);
-named!(response_auth<Vec<u8>>, preceded!(
- tag!(b"rspauth="),
- response_digest));
+named!(
+ response_auth<Vec<u8>>,
+ preceded!(tag!(b"rspauth="), response_digest)
+);
-named!(cnonce<Vec<u8>>, preceded!(
- tag!(b"cnonce="),
- quoted_string));
+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!(nonce_count<Vec<u8>>, preceded!(tag!(b"nc="), nc_value));
-named!(ainfo<AuthenticationInfo>, alt!(
+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!(
+ 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!(opaque<Vec<u8>>, preceded!(tag!(b"opaque="), quoted_string));
-named!(auth_param<AuthParam>, separated_pair!(
- token,
- tag!(b"="),
- alt!(
- token |
- quoted_string)));
+named!(
+ auth_param<AuthParam>,
+ separated_pair!(token, tag!(b"="), alt!(token | quoted_string))
+);
-named!(digest_response<Vec<DigestResponse>>, many1!(alt!(
+named!(
+ digest_response<Vec<DigestResponse>>,
+ many1!(alt!(
username => { |u| DigestResponse::Username(u) } |
realm => { |r| DigestResponse::Realm(r) } |
nonce => { |n| DigestResponse::Nonce(n) } |
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!(
+ 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!(
+ 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) }));
+ token => { |t| Purpose::Token(t) })
+);
-named!(info_param<InfoParam>, alt!(
+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!(
+ 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) }));
+ generic_param => {|g| ContactParam::Generic(g) })
+);
-named!(target<Target>,
- alt!(
+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!(
+ 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) })));
+ contact_target) => { |c| Contact::Contact(c) })
+ )
+);
-named!(disp_type<DispositionType>, alt!(
+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!(
+named!(
+ handling<Handling>,
+ alt!(
tag!(b"optional") => { |_| Handling::Optional } |
tag!(b"required") => { |_| Handling::Required } |
- token => { |t| Handling::Token(t) }));
+ token => { |t| Handling::Token(t) })
+);
-named!(disp_param<DispositionParam>, alt!(
+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!(
+ 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 }));
+ tag!(b"Sun") => { |_| Day::Sunday })
+);
-named!(month<Month>, alt!(
+named!(
+ month<Month>,
+ alt!(
tag!(b"Jan") => { |_| Month::January } |
tag!(b"Feb") => { |_| Month::February } |
tag!(b"Mar") => { |_| Month::March } |
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!(
+ 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!(
+ 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!(
+ 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"\"")
+ )
+);
+
+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!(
+ 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) })));
+ auth_param => { |(k, v)| DigestChallenge::AuthParam(k, v) }))
+);
use self::other_response as other_challenge;
-named!(challenge<Challenge>, alt!(
+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!(
+ 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)));
+ 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!(
+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!(
+ 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!(
+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));
+ 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!(
+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!(
+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!(
+)
+);
+
+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));
+ 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
use std;
use nom::alpha as alphas;
-use nom::digit as digits;
use nom::alphanumeric as alphanumerics;
+use nom::digit as digits;
-use nom::IResult;
use nom::ErrorKind::Custom;
+use nom::IResult;
macro_rules! take_1 (
($input:expr, $submac:ident!( $($args:tt)* )) => (
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};
+use types::{
+ AbsolutePath, AbsoluteUri, AcceptParam, AcceptRange, AlertParam, Algorithm, AuthParam,
+ AuthenticationInfo, Authority, CallId, Challenge, Coding, Contact, ContactParam, ContentCoding,
+ Credentials, Date, DateTime, Day, DigestChallenge, DigestResponse, DispositionParam,
+ DispositionType, Domain, Encoding, ErrorUri, From, FromParam, GenericParam, Handling, Header,
+ HierarchicalPath, Host, HostPort, Hostname, Info, InfoParam, Language, LanguageRange,
+ LanguageTag, MediaFullType, MediaMainType, MediaParameter, MediaRange, MediaType, Method,
+ Month, NameAddr, OptionTag, PathSegment, Priority, Protocol, Purpose, Qop, Received, ReplyTo,
+ RequestLine, RetryAfter, RetryAfterParam, Route, Scheme, SentProtocol, Server, SipUri,
+ StatusLine, Target, Time, To, ToParam, TopLine, Transport, Uri, UriHeader, UriHeaders,
+ UriParameter, UriPath, UserInfo, UserParam, Version, Via, ViaParam, Warning, WarningAgent,
+};
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))
+ 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')'
+ c == b'-'
+ || c == b'_'
+ || c == b'.'
+ || c == b'!'
+ || c == b'~'
+ || c == b'*'
+ || c == b'\''
+ || c == b'('
+ || c == b')'
}
fn is_unreserved(c: u8) -> bool {
}
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','
+ 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'/'
+ 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 {
}
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'~'
+ 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'}'
+ 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 {
named!(token<Vec<u8>>, many1!(take_1!(is_token)));
named!(word<Vec<u8>>, many1!(take_1!(is_word)));
-named!(method<Method>, alt!(
+named!(
+ method<Method>,
+ alt!(
// RFC 3261
tag!("INVITE") => { |_| Method::INVITE } |
tag!("ACK") => { |_| Method::ACK } |
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));
terminated!(top_label, opt!(tag!(b".")))));
fn number<O>(input: &[u8]) -> IResult<&[u8], O>
- where O: std::str::FromStr
+where
+ O: std::str::FromStr,
{
match digits(input) {
IResult::Done(left, num_str) => {
many1!(take_1!(is_ipv6_char)),
tag!(b"]")));
-named!(host<Host>, alt!(
+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!(
+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!(
+named!(
+ user_param<UserParam>,
+ alt!(
tag!("phone") => { |_| UserParam::Phone } |
tag!("ip") => { |_| UserParam::Ip } |
- token => { |token| UserParam::Other(token) }));
+ 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'$'
+ 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!(
+named!(
+ uri_parameter<UriParameter>,
+ alt!(
preceded!(tag!("transport="), transport_param) => {
|transport| UriParameter::Transport(transport)
} |
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'$'
+ is_unreserved(c)
+ || c == b'['
+ || c == b']'
+ || c == b'/'
+ || c == b'?'
+ || c == b':'
+ || c == b'+'
+ || c == b'$'
}
named!(hname<&[u8], Vec<u8>>, many1!(alt!(
tag!(b"&"),
uri_header)));
-type _SipUri = (Option<UserInfo>, HostPort, Vec<UriParameter>, Option<UriHeaders>);
+type _SipUri = (
+ Option<UserInfo>,
+ HostPort,
+ Vec<UriParameter>,
+ Option<UriHeaders>,
+);
named!(sip_uri<&[u8], _SipUri>, preceded!(
tag!("sip:"),
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','
+ 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!(
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','
+ 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!(
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','
+ 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!(
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!(
+ 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));
+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)
c <= 0x09 || c == 0x0B || c == 0x0C || (c >= 0x0E && c <= 0x7f)
}
-named!(qdpair<u8>, preceded!(
- tag!("\\"),
- take_1!(is_qdpair_char)));
+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!(
+ quoted_string<Vec<u8>>,
+ delimited!(tag!(b"\""), many0!(alt!(qdtext | qdpair)), tag!(b"\""))
+);