Support Contact header
authorRichard Whitehouse <github@richardwhiuk.com>
Sun, 29 Oct 2017 15:12:32 +0000 (15:12 +0000)
committerRichard Whitehouse <github@richardwhiuk.com>
Sun, 29 Oct 2017 15:12:32 +0000 (15:12 +0000)
src/codec.rs
src/parser.rs
src/types.rs

index 36eeff78abd86cc7e426bf5ab59c8cc6d04ff850..adce8bc968f7776ae0a38371828b2430b1a501b4 100644 (file)
@@ -432,7 +432,7 @@ mod tests {
                            MESSAGE\r\nAuthentication-Info:qop=auth\r\nAuthorization:Digest \
                            username=\"Alice\"\r\nCall-ID:f81d4fae-7dec-11d0-a765-00a0c91e6bf6@foo.\
                            bar.com\r\nCall-Info:<http://wwww.example.com/alice/photo.jpg>;\
-                           purpose=icon\r\nVia: localhost\r\n\r\n")
+                           purpose=icon\r\nContact:*\r\nVia: localhost\r\n\r\n")
         });
 
         let finished = request.and_then(|(socket, _request)| {
index 3e4b202d243ebbeb7352c9928c5b31b604ce571c..1e77e48732796fe1aa98b8dd7b0e313ce47f51f9 100644 (file)
@@ -14,7 +14,7 @@ use types::{PathSegment, HostPort, Host, Hostname, UriParameter, UriHeader, UriH
             Header, MediaType, MediaFullType, MediaParameter, MediaRange, GenericParam,
             AcceptParam, AcceptRange, Coding, Encoding, LanguageRange, Language, AlertParam, Qop,
             AuthenticationInfo, AuthParam, Algorithm, DigestResponse, Credentials, CallId,
-            Purpose, InfoParam, Info};
+            Purpose, InfoParam, Info, NameAddr, ContactParam, ContactTarget, Contact};
 
 fn is_mark(c: u8) -> bool {
     c == b'-' || c == b'_' || c == b'.' || c == b'!' || c == b'~' || c == b'*' || c == b'\'' ||
@@ -392,7 +392,7 @@ named!(absolute_uri<&[u8], AbsoluteUri>, separated_pair!(
       opaque_part => { |(b, o)| UriPath::Opaque(b, o) }
     )));
 
-named!(request_uri<&[u8], Uri>, alt!(
+named!(uri<&[u8], Uri>, alt!(
     sip_uri => { |(u, hp, p, h)| Uri::Sip(SipUri {
         user_info: u,
         host_port: hp,
@@ -419,7 +419,7 @@ named!(request_line<&[u8], (Method, Uri, Version)>, tuple!(
     method,
     delimited!(
         tag!(" "),
-        request_uri,
+        uri,
         tag!(" ")),
     sip_version));
 
@@ -522,8 +522,10 @@ named!(generic_param<GenericParam>, separated_pair!(
 
 use nom::float as qvalue;
 
+named!(qparam<f32>, preceded!(tag!(b"q="), qvalue));
+
 named!(accept_param<AcceptParam>, alt!(
-       preceded!(tag!(b"q"), qvalue) => { |x| AcceptParam::Qvalue(x) } |
+       qparam => { |x| AcceptParam::Qvalue(x) } |
        generic_param => { |x| AcceptParam::Generic(x) }));
 
 named!(accept_range<AcceptRange>, tuple!(
@@ -745,6 +747,43 @@ named!(call_info_header<Vec<Info>>, preceded!(
                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!(contact_target<(ContactTarget, Vec<ContactParam>)>, tuple!(
+       alt!(
+               name_addr => { |(n, u)| ContactTarget::Name(n, u) } |
+               uri => { |u| ContactTarget::Uri(u) }),
+       many0!(preceded!(
+               tag!(b";"),
+               contact_param
+       ))));
+
+named!(contact_header<Contact>, preceded!(
+       alt!(tag!(b"Contact:") | tag!(b"m")),
+       alt!(
+               tag!(b"*") => { |_| Contact::Star } |
+               separated_nonempty_list!(
+                       tag!(","),
+                       contact_target) => { |c| Contact::Contact(c) })));
+
 named!(pub header<Header>, alt!(
 // RFC 3261 Headers
        accept_header => { |a| Header::Accept(a) } |
@@ -755,5 +794,6 @@ named!(pub header<Header>, alt!(
        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) }
+       call_info_header => { |c| Header::CallInfo(c) } |
+       contact_header => { |c| Header::Contact(c) }
 ));
index e05f4e4db845e59733d6a0bb524f0ffa71b6386c..22785281068538a85a6470c46a9dfd6243eca91a 100644 (file)
@@ -249,6 +249,27 @@ pub enum InfoParam {
 
 pub type Info = (AbsoluteUri, Vec<InfoParam>);
 
+pub type NameAddr = (Option<Vec<u8>>, Uri);
+
+#[derive(Debug)]
+pub enum ContactParam {
+    Qvalue(f32),
+    Expires(u32),
+    Generic(GenericParam),
+}
+
+#[derive(Debug)]
+pub enum ContactTarget {
+    Name(Option<Vec<u8>>, Uri),
+    Uri(Uri),
+}
+
+#[derive(Debug)]
+pub enum Contact {
+    Star,
+    Contact(Vec<(ContactTarget, Vec<ContactParam>)>),
+}
+
 #[derive(Debug)]
 pub enum Header {
     Accept(Vec<AcceptRange>),
@@ -260,6 +281,7 @@ pub enum Header {
     Authorization(Credentials),
     CallId(CallId),
     CallInfo(Vec<Info>),
+    Contact(Contact),
     From(Uri),
     To(Uri),
     Extension { name: String, value: String },