--- 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