Support From header
authorRichard Whitehouse <github@richardwhiuk.com>
Sun, 29 Oct 2017 18:25:38 +0000 (18:25 +0000)
committerRichard Whitehouse <github@richardwhiuk.com>
Sun, 29 Oct 2017 18:31:34 +0000 (18:31 +0000)
src/codec.rs
src/parser.rs
src/types.rs

index 4c9a348a999cf17ee287d7ca348fc713d6ffa1bc..8a17c2fb188ed4ffc91613edb31c066658644358 100644 (file)
@@ -437,7 +437,8 @@ mod tests {
                            en-gb\r\nContent-Length:0\r\nContent-Type:text/plain\r\nCSeq:1 \
                            MESSAGE\r\nDate:Sat, 13 Nov 2010 23:29:00 \
                            GMT\r\nError-Info:<sip:not-in-service-recording@atlanta.\
-                           com>\r\nExpires:30\r\nVia: localhost\r\n\r\n")
+                           com>\r\nExpires:30\r\nFrom:sip:+12125551212@server.phone2net.com;\
+                           tag=887s\r\nVia: localhost\r\n\r\n")
         });
 
         let finished = request.and_then(|(socket, _request)| {
index 6bcb5739b0d8850f92e44ab1021dc7e0e0f9ae07..7216409eeb3a7f30859c45d33c392e52e17e6eab 100644 (file)
@@ -14,9 +14,9 @@ use types::{PathSegment, HostPort, Host, Hostname, UriParameter, UriHeader, UriH
             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, ContactTarget,
+            Credentials, CallId, Purpose, InfoParam, Info, NameAddr, ContactParam, Target,
             Contact, DispositionType, Handling, DispositionParam, ContentCoding, Day, Month, Date,
-            Time, DateTime, ErrorUri};
+            Time, DateTime, ErrorUri, FromParam, From};
 
 fn is_mark(c: u8) -> bool {
     c == b'-' || c == b'_' || c == b'.' || c == b'!' || c == b'~' || c == b'*' || c == b'\'' ||
@@ -311,6 +311,22 @@ named!(sips_uri<&[u8], _SipUri>, preceded!(
         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'.'
 }
@@ -410,6 +426,23 @@ named!(uri<&[u8], Uri>, alt!(
         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!(
@@ -771,10 +804,15 @@ named!(contact_param<ContactParam>, alt!(
        expires => {|e| ContactParam::Expires(e) } |
        generic_param => {|g| ContactParam::Generic(g) }));
 
-named!(contact_target<(ContactTarget, Vec<ContactParam>)>, tuple!(
+named!(target<Target>,
        alt!(
-               name_addr => { |(n, u)| ContactTarget::Name(n, u) } |
-               uri => { |u| ContactTarget::Uri(u) }),
+               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
@@ -902,6 +940,18 @@ named!(expires_header<u32>, preceded!(
        tag!(b"Expires:"),
        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!(
+       alt!(tag!(b"From:") | tag!("f:")),
+       tuple!(
+               target,
+               many0!(preceded!(
+                       tag!(b";"),
+                       from_param)))));
+
 named!(pub header<Header>, alt!(
 // RFC 3261 Headers
        accept_header => { |a| Header::Accept(a) } |
@@ -922,5 +972,6 @@ named!(pub header<Header>, alt!(
        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) }
+       expires_header => { |e| Header::Expires(e) } |
+       from_header => { |f| Header::From(f) }
 ));
index 6fab135de8a98a08339ea3c32488d3d9ba155f1c..1afad387b2a416609e3d7e7d81fc0ed3aa61c27b 100644 (file)
@@ -263,7 +263,7 @@ pub enum ContactParam {
 }
 
 #[derive(Debug)]
-pub enum ContactTarget {
+pub enum Target {
     Name(Option<Vec<u8>>, Uri),
     Uri(Uri),
 }
@@ -271,7 +271,7 @@ pub enum ContactTarget {
 #[derive(Debug)]
 pub enum Contact {
     Star,
-    Contact(Vec<(ContactTarget, Vec<ContactParam>)>),
+    Contact(Vec<(Target, Vec<ContactParam>)>),
 }
 
 #[derive(Debug)]
@@ -333,6 +333,14 @@ pub type DateTime = (Day, Date, Time);
 
 pub type ErrorUri = (AbsoluteUri, Vec<GenericParam>);
 
+#[derive(Debug)]
+pub enum FromParam {
+    Tag(Vec<u8>),
+    Generic(GenericParam),
+}
+
+pub type From = (Target, Vec<FromParam>);
+
 #[derive(Debug)]
 pub enum Header {
     Accept(Vec<AcceptRange>),
@@ -354,7 +362,7 @@ pub enum Header {
     Date(DateTime),
     ErrorInfo(Vec<ErrorUri>),
     Expires(u32),
-    From(Uri),
+    From(From),
     To(Uri),
     Extension { name: String, value: String },
 }