Bug 1437166: Part 1: Implemented ssrc-group attribute parsing in rust. r=bwc draft
authorJohannes Willbold <j.willbold@mozilla.com>
Thu, 21 Jun 2018 12:31:36 -0700
changeset 809323 bfa8e97836a0a8ac8ab24f3ffba57be8fce51b66
parent 808726 681eb7dfa324dd50403c382888929ea8b8b11b00
child 809324 4d89745a75c4e1f0d42cdd1e262aeae2391fd41f
push id113640
push userbmo:johannes.willbold@rub.de
push dateThu, 21 Jun 2018 20:56:30 +0000
reviewersbwc
bugs1437166
milestone62.0a1
Bug 1437166: Part 1: Implemented ssrc-group attribute parsing in rust. r=bwc Implemented ssrc-group attribute parsing in rust Extended rust test case test_parse_attribute_ssrc_group MozReview-Commit-ID: Gyh4SDzvONS
media/webrtc/signaling/src/sdp/rsdparsa/src/attribute_type.rs
--- a/media/webrtc/signaling/src/sdp/rsdparsa/src/attribute_type.rs
+++ b/media/webrtc/signaling/src/sdp/rsdparsa/src/attribute_type.rs
@@ -389,16 +389,32 @@ impl SdpAttributeSsrc {
             self.attribute = Some(v[0].to_string());
             self.value = Some(v[1].to_string());
         }
     }
 }
 
 #[derive(Clone)]
 #[cfg_attr(feature="serialize", derive(Serialize))]
+pub enum SdpAttributeSsrcGroupSemantics {
+    Fec,   // RFC5576
+    Fid,   // RFC5576
+    FecFr, // RFC5956
+    Dup,   // RFC7104
+}
+
+#[derive(Clone)]
+#[cfg_attr(feature="serialize", derive(Serialize))]
+pub struct SdpAttributeSsrcGroup {
+    pub semantics: SdpAttributeSsrcGroupSemantics,
+    pub ssrcs: Vec<u32>,
+}
+
+#[derive(Clone)]
+#[cfg_attr(feature="serialize", derive(Serialize))]
 pub enum SdpAttribute {
     BundleOnly,
     Candidate(SdpAttributeCandidate),
     EndOfCandidates,
     Extmap(SdpAttributeExtmap),
     Fingerprint(SdpAttributeFingerprint),
     Fmtp(SdpAttributeFmtp),
     Group(SdpAttributeGroup),
@@ -427,17 +443,17 @@ pub enum SdpAttribute {
     RtcpRsize,
     Sctpmap(SdpAttributeSctpmap),
     SctpPort(u64),
     Sendonly,
     Sendrecv,
     Setup(SdpAttributeSetup),
     Simulcast(SdpAttributeSimulcast),
     Ssrc(SdpAttributeSsrc),
-    SsrcGroup(String),
+    SsrcGroup(SdpAttributeSsrcGroup),
 }
 
 impl SdpAttribute {
     pub fn allowed_at_session_level(&self) -> bool {
         match *self {
             SdpAttribute::BundleOnly |
             SdpAttribute::Candidate(..) |
             SdpAttribute::Fmtp(..) |
@@ -615,17 +631,17 @@ impl FromStr for SdpAttribute {
             "msid-semantic" => parse_msid_semantic(val),
             "ptime" => Ok(SdpAttribute::Ptime(val.parse()?)),
             "rid" => Ok(SdpAttribute::Rid(string_or_empty(val)?)),
             "recvonly" => Ok(SdpAttribute::Recvonly),
             "rtcp-mux" => Ok(SdpAttribute::RtcpMux),
             "rtcp-rsize" => Ok(SdpAttribute::RtcpRsize),
             "sendonly" => Ok(SdpAttribute::Sendonly),
             "sendrecv" => Ok(SdpAttribute::Sendrecv),
-            "ssrc-group" => Ok(SdpAttribute::SsrcGroup(string_or_empty(val)?)),
+            "ssrc-group" => parse_ssrc_group(val),
             "sctp-port" => parse_sctp_port(val),
             "candidate" => parse_candidate(val),
             "extmap" => parse_extmap(val),
             "fingerprint" => parse_fingerprint(val),
             "fmtp" => parse_fmtp(val),
             "group" => parse_group(val),
             "ice-options" => parse_ice_options(val),
             "msid" => parse_msid(val),
@@ -1475,16 +1491,49 @@ fn parse_ssrc(to_parse: &str) -> Result<
     let mut ssrc = SdpAttributeSsrc::new(ssrc_id);
     match tokens.next() {
         None => (),
         Some(x) => ssrc.set_attribute(x),
     };
     Ok(SdpAttribute::Ssrc(ssrc))
 }
 
+fn parse_ssrc_group(to_parse: &str) -> Result<SdpAttribute, SdpParserInternalError> {
+    let tokens: Vec<&str> = to_parse.splitn(2, " ").collect();
+
+    if tokens.len() < 2 {
+        return Err(SdpParserInternalError::Generic(
+            "A ssrc-group attribute must have a semantics token and a ssrc id list".to_string()
+        ))
+    }
+
+    let semantics = match tokens[0] {
+        "FEC" => SdpAttributeSsrcGroupSemantics::Fec,
+        "FID" => SdpAttributeSsrcGroupSemantics::Fid,
+        "FEC-FR" => SdpAttributeSsrcGroupSemantics::FecFr,
+        "DUP" => SdpAttributeSsrcGroupSemantics::Dup,
+        x @ _ => {
+            return Err(SdpParserInternalError::Generic(
+                format!("ssrc-group contains unknown semantics token: '{:?}'",x).to_string()
+            ))
+        }
+    };
+
+    let mut ssrcs: Vec<u32> = Vec::new();
+    let ssrcs_tokens = tokens[1].split_whitespace();
+    for ssrc_token in ssrcs_tokens {
+        ssrcs.push(ssrc_token.parse::<u32>()?);
+    }
+
+    Ok(SdpAttribute::SsrcGroup(SdpAttributeSsrcGroup {
+        semantics,
+        ssrcs
+    }))
+}
+
 pub fn parse_attribute(value: &str) -> Result<SdpType, SdpParserInternalError> {
     Ok(SdpType::Attribute(value.trim().parse()?))
 }
 
 #[test]
 fn test_parse_attribute_candidate() {
     assert!(parse_attribute("candidate:0 1 UDP 2122252543 172.16.156.106 49760 typ host").is_ok());
     assert!(parse_attribute("candidate:foo 1 UDP 2122252543 172.16.156.106 49760 typ host")
@@ -1883,17 +1932,29 @@ fn test_parse_attribute_ssrc() {
                 .is_ok());
 
     assert!(parse_attribute("ssrc:").is_err());
     assert!(parse_attribute("ssrc:foo").is_err());
 }
 
 #[test]
 fn test_parse_attribute_ssrc_group() {
-    assert!(parse_attribute("ssrc-group:FID 3156517279 2673335628").is_ok())
+    assert!(parse_attribute("ssrc-group:FEC 3333 4444").is_ok());
+    assert!(parse_attribute("ssrc-group: FEC 3333 4444").is_ok());
+    assert!(parse_attribute("ssrc-group:FID 3333 4444 6").is_ok());
+    assert!(parse_attribute("ssrc-group:FEC-FR 3333").is_ok());
+    assert!(parse_attribute("ssrc-group: FEC-FR 3333 ").is_ok());
+    assert!(parse_attribute("ssrc-group:DUP 3333 99 10 100").is_ok());
+    assert!(parse_attribute("ssrc-group:FID 3156517279 2673335628").is_ok());
+
+    assert!(parse_attribute("ssrc-group:FEC").is_err());
+    assert!(parse_attribute("ssrc-group:foo").is_err());
+    assert!(parse_attribute("ssrc-group:foo 3333 99 10 100").is_err());
+    assert!(parse_attribute("ssrc-group:fec 3333 99 10 100").is_err());
+    assert!(parse_attribute("ssrc-group:fec 3333 99 10 100").is_err());
 }
 
 #[test]
 fn test_parse_unknown_attribute() {
     assert!(parse_attribute("unknown").is_err())
 }
 
 // Returns true if valid byte-string as defined by RFC 4566