Support Authentication-Info header
authorRichard Whitehouse <github@richardwhiuk.com>
Sun, 29 Oct 2017 13:23:25 +0000 (13:23 +0000)
committerRichard Whitehouse <github@richardwhiuk.com>
Sun, 29 Oct 2017 13:23:25 +0000 (13:23 +0000)
src/codec.rs
src/parser.rs
src/types.rs

index 7fa20c038088181033bddd828ee124d61c8d8631..0c12300b3e7fc706a0d2ae542eff79c65ba279f9 100644 (file)
@@ -428,8 +428,8 @@ mod tests {
             io::write_all(socket,
                           "MESSAGE sip:test.com \
                            SIP/2.0\r\nAccept:text/plain\r\nAccept-Encoding:*\r\nAccept-Language:\
-                           en-gb\r\nAlert-Info:<http://www.example.com/sounds/moo.wav>\r\nAllow:MESSAGE\r\nVia: \
-                           localhost\r\n\r\n")
+                           en-gb\r\nAlert-Info:<http://www.example.com/sounds/moo.wav>\r\nAllow:\
+                           MESSAGE\r\nAuthentication-Info:qop=auth\r\nVia: localhost\r\n\r\n")
         });
 
         let finished = request.and_then(|(socket, _request)| {
index fa4051d75a7d6f036dd157b1f46b93135a20fab7..4d6330cba37677a9ad7befab0b9001a891e79837 100644 (file)
@@ -12,7 +12,8 @@ use types::{PathSegment, HostPort, Host, Hostname, UriParameter, UriHeader, UriH
             AbsoluteUri, Uri, HierarchicalPath, Authority, UriPath, UserInfo, AbsolutePath,
             Scheme, Method, Transport, UserParam, Version, RequestLine, StatusLine, TopLine,
             Header, MediaType, MediaFullType, MediaParameter, MediaRange, GenericParam,
-            AcceptParam, AcceptRange, Coding, Encoding, LanguageRange, Language, AlertParam};
+            AcceptParam, AcceptRange, Coding, Encoding, LanguageRange, Language, AlertParam, Qop,
+            AuthenticationInfo};
 
 fn is_mark(c: u8) -> bool {
     c == b'-' || c == b'_' || c == b'.' || c == b'!' || c == b'~' || c == b'*' || c == b'\'' ||
@@ -78,6 +79,10 @@ fn is_token(c: u8) -> bool {
     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!(method<Method>, alt!(
@@ -100,6 +105,7 @@ 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));
@@ -583,11 +589,57 @@ named!(allow_header<Vec<Method>>, preceded!(
                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!(
+       tag!(b"Authentication-Info:"),
+       separated_nonempty_list!(
+               tag!(b","),
+               ainfo)));
+
 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) }
+       allow_header => { |a| Header::Allow(a) } |
+       authentication_info_header => { |a| Header::AuthenticationInfo(a) }
 ));
index cc3c842686caf6a6412aff22acba7919bbe0a28d..3920bc894f4a0b07f69406a851f9022b61b311fd 100644 (file)
@@ -185,6 +185,22 @@ pub type Language = (LanguageRange, Vec<AcceptParam>);
 
 pub type AlertParam = (AbsoluteUri, Vec<GenericParam>);
 
+#[derive(Debug)]
+pub enum Qop {
+    Auth,
+    AuthInit,
+    Token(Vec<u8>),
+}
+
+#[derive(Debug)]
+pub enum AuthenticationInfo {
+    NextNonce(Vec<u8>),
+    MessageQop(Qop),
+    ResponseAuth(Vec<u8>),
+    Cnonce(Vec<u8>),
+    NonceCount(Vec<u8>),
+}
+
 #[derive(Debug)]
 pub enum Header {
     Accept(Vec<AcceptRange>),
@@ -192,6 +208,7 @@ pub enum Header {
     AcceptLanguage(Vec<Language>),
     AlertInfo(Vec<AlertParam>),
     Allow(Vec<Method>),
+    AuthenticationInfo(Vec<AuthenticationInfo>),
     From(Uri),
     To(Uri),
     Extension { name: String, value: String },