@@ -417,6 +417,14 @@
<xmpp:since>NEXT</xmpp:since>
</xmpp:SupportedXep>
</implements>
+ <implements>
+ <xmpp:SupportedXep>
+ <xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0339.html"/>
+ <xmpp:status>complete</xmpp:status>
+ <xmpp:version>0.3</xmpp:version>
+ <xmpp:since>NEXT</xmpp:since>
+ </xmpp:SupportedXep>
+ </implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0352.html"/>
@@ -4,6 +4,8 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+use crate::jingle_ssma::{Source, Group};
+
generate_element!(
/// Wrapper element describing an RTP session.
Description, "description", JINGLE_RTP,
@@ -18,7 +20,13 @@ generate_element!(
],
children: [
/// List of encodings that can be used for this RTP stream.
- payload_types: Vec<PayloadType> = ("payload-type", JINGLE_RTP) => PayloadType
+ payload_types: Vec<PayloadType> = ("payload-type", JINGLE_RTP) => PayloadType,
+
+ /// List of ssrc-group.
+ ssrc_groups: Vec<Group> = ("ssrc-group", JINGLE_SSMA) => Group,
+
+ /// List of ssrc.
+ ssrcs: Vec<Source> = ("ssrc", JINGLE_SSMA) => Source
// TODO: Add support for <encryption/> and <bandwidth/>.
]
@@ -31,6 +39,8 @@ impl Description {
media,
ssrc: None,
payload_types: Vec::new(),
+ ssrc_groups: Vec::new(),
+ ssrcs: Vec::new(),
}
}
}
@@ -0,0 +1,114 @@
+// Copyright (c) 2019 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+generate_element!(
+ /// Source element for the ssrc SDP attribute.
+ Source, "source", JINGLE_SSMA,
+ attributes: [
+ /// Maps to the ssrc-id parameter.
+ id: Required<String> = "ssrc",
+ ],
+ children: [
+ /// List of attributes for this source.
+ parameters: Vec<Parameter> = ("parameter", JINGLE_SSMA) => Parameter
+ ]
+);
+
+impl Source {
+ /// Create a new SSMA Source element.
+ pub fn new(id: String) -> Source {
+ Source {
+ id,
+ parameters: Vec::new(),
+ }
+ }
+}
+
+generate_element!(
+ /// Parameter associated with a ssrc.
+ Parameter, "parameter", JINGLE_SSMA,
+ attributes: [
+ /// The name of the parameter.
+ name: Required<String> = "name",
+
+ /// The optional value of the parameter.
+ value: Option<String> = "value",
+ ]
+);
+
+generate_element!(
+ /// Element grouping multiple ssrc.
+ Group, "ssrc-group", JINGLE_SSMA,
+ attributes: [
+ /// The semantics of this group.
+ semantics: Required<String> = "semantics",
+ ],
+ children: [
+ /// The various ssrc concerned by this group.
+ sources: Vec<Source> = ("source", JINGLE_SSMA) => Source
+ ]
+);
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::Element;
+ use std::convert::TryFrom;
+
+ #[cfg(target_pointer_width = "32")]
+ #[test]
+ fn test_size() {
+ assert_size!(Source, 24);
+ assert_size!(Parameter, 24);
+ assert_size!(Group, 24);
+ }
+
+ #[cfg(target_pointer_width = "64")]
+ #[test]
+ fn test_size() {
+ assert_size!(Source, 48);
+ assert_size!(Parameter, 48);
+ assert_size!(Group, 48);
+ }
+
+ #[test]
+ fn parse_source() {
+ let elem: Element = "
+<source ssrc='1656081975' xmlns='urn:xmpp:jingle:apps:rtp:ssma:0'>
+ <parameter name='cname' value='Yv/wvbCdsDW2Prgd'/>
+ <parameter name='msid' value='MLTJKIHilGn71fNQoszkQ4jlPTuS5vJyKVIv MLTJKIHilGn71fNQoszkQ4jlPTuS5vJyKVIva0'/>
+</source>"
+ .parse()
+ .unwrap();
+ let mut ssrc = Source::try_from(elem).unwrap();
+ assert_eq!(ssrc.id, "1656081975");
+ assert_eq!(ssrc.parameters.len(), 2);
+ let parameter = ssrc.parameters.pop().unwrap();
+ assert_eq!(parameter.name, "msid");
+ assert_eq!(parameter.value.unwrap(), "MLTJKIHilGn71fNQoszkQ4jlPTuS5vJyKVIv MLTJKIHilGn71fNQoszkQ4jlPTuS5vJyKVIva0");
+ let parameter = ssrc.parameters.pop().unwrap();
+ assert_eq!(parameter.name, "cname");
+ assert_eq!(parameter.value.unwrap(), "Yv/wvbCdsDW2Prgd");
+ }
+
+ #[test]
+ fn parse_source_group() {
+ let elem: Element = "
+<ssrc-group semantics='FID' xmlns='urn:xmpp:jingle:apps:rtp:ssma:0'>
+ <source ssrc='2301230316'/>
+ <source ssrc='386328120'/>
+</ssrc-group>"
+ .parse()
+ .unwrap();
+ let mut group = Group::try_from(elem).unwrap();
+ assert_eq!(group.semantics, "FID");
+ assert_eq!(group.sources.len(), 2);
+ let source = group.sources.pop().unwrap();
+ assert_eq!(source.id, "386328120");
+ let source = group.sources.pop().unwrap();
+ assert_eq!(source.id, "2301230316");
+ }
+}
@@ -183,6 +183,9 @@ pub mod jingle_dtls_srtp;
/// XEP-0328: JID Prep
pub mod jid_prep;
+/// XEP-0339: Source-Specific Media Attributes in Jingle
+pub mod jingle_ssma;
+
/// XEP-0352: Client State Indication
pub mod csi;
@@ -188,6 +188,9 @@ pub const JINGLE_DTLS: &str = "urn:xmpp:jingle:apps:dtls:0";
/// XEP-0328: JID Prep
pub const JID_PREP: &str = "urn:xmpp:jidprep:0";
+/// XEP-0339: Source-Specific Media Attributes in Jingle
+pub const JINGLE_SSMA: &str = "urn:xmpp:jingle:apps:rtp:ssma:0";
+
/// XEP-0352: Client State Indication
pub const CSI: &str = "urn:xmpp:csi:0";