Add method to return branch for a request master
authorRichard Whitehouse <github@richardwhiuk.com>
Tue, 23 Oct 2018 00:18:41 +0000 (20:18 -0400)
committerRichard Whitehouse <github@richardwhiuk.com>
Tue, 23 Oct 2018 00:20:15 +0000 (20:20 -0400)
src/codec/mod.rs
src/message.rs

index 56b74fa9834fd2e66af186eede59be0113d3ecb9..2655436037ac0d9aceb876b6901156ac973dc27c 100644 (file)
@@ -34,7 +34,7 @@ impl UnparsedLine {
     }
 
     #[cfg(test)]
-    fn from_bytes(value: &[u8]) -> UnparsedLine {
+    pub fn from_bytes(value: &[u8]) -> UnparsedLine {
         let mut b = BytesMut::new();
         b.extend_from_slice(value);
         UnparsedLine::new(b)
index 39edba6789bab3671f34e330d7db0e18a16bf008..a9cbad898767692fd8beaa5d8f9ce77567b6093e 100644 (file)
@@ -1,7 +1,7 @@
 use bytes::BytesMut;
 
 use codec::UnparsedLine;
-use types::{Header, Method, RequestLine, StatusLine};
+use types::{Header, Method, RequestLine, StatusLine, ViaParam};
 
 #[derive(Debug)]
 pub enum Message {
@@ -72,4 +72,72 @@ impl Request {
     pub fn method(&self) -> &Method {
         &self.request_line.0.method
     }
+
+    pub fn branch(&self) -> Option<&Vec<u8>> {
+        // Get the first Via header
+        let h = self
+            .headers
+            .iter()
+            .filter_map(|h| {
+                if let Header::Via(ref v) = h.0 {
+                    Some(v.first())
+                } else {
+                    None
+                }
+            }).next();
+
+        if let Some(Some(v)) = h {
+            // This will return None if the Via header doesn't have a branch
+            // parameter in contravention of RFC 3261 Section 8.1.17
+            v.2.iter()
+                .filter_map(|p| {
+                    if let ViaParam::Branch(b) = p {
+                        Some(b)
+                    } else {
+                        None
+                    }
+                }).next()
+        } else {
+            // Either no Via headers, or first via header
+            // has no Via parameters
+            None
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+
+    use super::*;
+    use types::{Host, Method, Protocol, SipUri, Transport, Uri};
+
+    #[test]
+    fn test_request_branch_mainline() {
+        let r = Request {
+            request_line: (
+                RequestLine {
+                    method: Method::MESSAGE,
+                    uri: Uri::Sip(SipUri {
+                        user_info: None,
+                        host_port: (Host::Ipv4Address(127, 0, 0, 1), None),
+                        params: vec![],
+                        headers: None,
+                    }),
+                    version: (2, 0),
+                },
+                UnparsedLine::from_bytes(b"MESSAGE sip:127.0.0.1 SIP/2.0"),
+            ),
+            headers: vec![(
+                Header::Via(vec![(
+                    (Protocol::SIP, vec![2, 0], Transport::Tcp),
+                    (Host::Ipv4Address(127, 0, 0, 1), None),
+                    vec![ViaParam::Branch(b"abcdef".to_vec())],
+                )]),
+                UnparsedLine::from_bytes(b"Via: TCP/2.0/TCP 127.0.0.1;branch=abcdef"),
+            )],
+            body: None,
+        };
+
+        assert_eq!(*r.branch().expect("Expected branch"), b"abcdef".to_vec());
+    }
 }