jingle_rtp.rs

  1// Copyright (c) 2019 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
  2//
  3// This Source Code Form is subject to the terms of the Mozilla Public
  4// License, v. 2.0. If a copy of the MPL was not distributed with this
  5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
  6
  7use crate::jingle_ssma::{Source, Group};
  8
  9generate_element!(
 10    /// Wrapper element describing an RTP session.
 11    Description, "description", JINGLE_RTP,
 12    attributes: [
 13        /// Namespace of the encryption scheme used.
 14        media: Required<String> = "media",
 15
 16        /// User-friendly name for the encryption scheme, should be `None` for OTR,
 17        /// legacy OpenPGP and OX.
 18        // XXX: is this a String or an u32?!  Refer to RFC 3550.
 19        ssrc: Option<String> = "ssrc",
 20    ],
 21    children: [
 22        /// List of encodings that can be used for this RTP stream.
 23        payload_types: Vec<PayloadType> = ("payload-type", JINGLE_RTP) => PayloadType,
 24
 25        /// List of ssrc-group.
 26        ssrc_groups: Vec<Group> = ("ssrc-group", JINGLE_SSMA) => Group,
 27
 28        /// List of ssrc.
 29        ssrcs: Vec<Source> = ("ssrc", JINGLE_SSMA) => Source
 30
 31        // TODO: Add support for <encryption/> and <bandwidth/>.
 32    ]
 33);
 34
 35impl Description {
 36    /// Create a new RTP description.
 37    pub fn new(media: String) -> Description {
 38        Description {
 39            media,
 40            ssrc: None,
 41            payload_types: Vec::new(),
 42            ssrc_groups: Vec::new(),
 43            ssrcs: Vec::new(),
 44        }
 45    }
 46}
 47
 48generate_attribute!(
 49    /// The number of channels.
 50    Channels, "channels", u8, Default = 1
 51);
 52
 53generate_element!(
 54    /// An encoding that can be used for an RTP stream.
 55    PayloadType, "payload-type", JINGLE_RTP,
 56    attributes: [
 57        /// The number of channels.
 58        channels: Default<Channels> = "channels",
 59
 60        /// The sampling frequency in Hertz.
 61        clockrate: Option<u32> = "clockrate",
 62
 63        /// The payload identifier.
 64        id: Required<u8> = "id",
 65
 66        /// Maximum packet time as specified in RFC 4566.
 67        maxptime: Option<u32> = "maxptime",
 68
 69        /// The appropriate subtype of the MIME type.
 70        name: Option<String> = "name",
 71
 72        /// Packet time as specified in RFC 4566.
 73        ptime: Option<u32> = "ptime",
 74    ],
 75    children: [
 76        /// List of parameters specifying this payload-type.
 77        ///
 78        /// Their order MUST be ignored.
 79        parameters: Vec<Parameter> = ("parameter", JINGLE_RTP) => Parameter
 80    ]
 81);
 82
 83impl PayloadType {
 84    /// Create a new RTP payload-type.
 85    pub fn new(id: u8, name: String) -> PayloadType {
 86        PayloadType {
 87            channels: Default::default(),
 88            clockrate: None,
 89            id,
 90            maxptime: None,
 91            name: Some(name),
 92            ptime: None,
 93            parameters: Vec::new(),
 94        }
 95    }
 96}
 97
 98generate_element!(
 99    /// Parameter related to a payload.
100    Parameter, "parameter", JINGLE_RTP,
101    attributes: [
102        /// The name of the parameter, from the list at
103        /// https://www.iana.org/assignments/sdp-parameters/sdp-parameters.xhtml
104        name: Required<String> = "name",
105
106        /// The value of this parameter.
107        value: Required<String> = "value",
108    ]
109);
110
111#[cfg(test)]
112mod tests {
113    use super::*;
114    use crate::Element;
115    use std::convert::TryFrom;
116
117    #[cfg(target_pointer_width = "32")]
118    #[test]
119    fn test_size() {
120        assert_size!(Description, 36);
121        assert_size!(Channels, 1);
122        assert_size!(PayloadType, 52);
123        assert_size!(Parameter, 24);
124    }
125
126    #[cfg(target_pointer_width = "64")]
127    #[test]
128    fn test_size() {
129        assert_size!(Description, 72);
130        assert_size!(Channels, 1);
131        assert_size!(PayloadType, 80);
132        assert_size!(Parameter, 48);
133    }
134
135    #[test]
136    fn test_simple() {
137        let elem: Element = "
138<description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'>
139    <payload-type xmlns='urn:xmpp:jingle:apps:rtp:1' channels='2' clockrate='48000' id='96' name='OPUS'/>
140    <payload-type xmlns='urn:xmpp:jingle:apps:rtp:1' channels='1' clockrate='32000' id='105' name='SPEEX'/>
141    <payload-type xmlns='urn:xmpp:jingle:apps:rtp:1' channels='1' clockrate='8000' id='9' name='G722'/>
142    <payload-type xmlns='urn:xmpp:jingle:apps:rtp:1' channels='1' clockrate='16000' id='106' name='SPEEX'/>
143    <payload-type xmlns='urn:xmpp:jingle:apps:rtp:1' clockrate='8000' id='8' name='PCMA'/>
144    <payload-type xmlns='urn:xmpp:jingle:apps:rtp:1' clockrate='8000' id='0' name='PCMU'/>
145    <payload-type xmlns='urn:xmpp:jingle:apps:rtp:1' channels='1' clockrate='8000' id='107' name='SPEEX'/>
146    <payload-type xmlns='urn:xmpp:jingle:apps:rtp:1' channels='1' clockrate='8000' id='99' name='AMR'>
147        <parameter xmlns='urn:xmpp:jingle:apps:rtp:1' name='octet-align' value='1'/>
148        <parameter xmlns='urn:xmpp:jingle:apps:rtp:1' name='crc' value='0'/>
149        <parameter xmlns='urn:xmpp:jingle:apps:rtp:1' name='robust-sorting' value='0'/>
150        <parameter xmlns='urn:xmpp:jingle:apps:rtp:1' name='interleaving' value='0'/>
151    </payload-type>
152    <payload-type xmlns='urn:xmpp:jingle:apps:rtp:1' clockrate='48000' id='100' name='telephone-event'>
153        <parameter xmlns='urn:xmpp:jingle:apps:rtp:1' name='events' value='0-15'/>
154    </payload-type>
155    <payload-type xmlns='urn:xmpp:jingle:apps:rtp:1' clockrate='16000' id='101' name='telephone-event'>
156        <parameter xmlns='urn:xmpp:jingle:apps:rtp:1' name='events' value='0-15'/>
157    </payload-type>
158    <payload-type xmlns='urn:xmpp:jingle:apps:rtp:1' clockrate='8000' id='102' name='telephone-event'>
159        <parameter xmlns='urn:xmpp:jingle:apps:rtp:1' name='events' value='0-15'/>
160    </payload-type>
161</description>"
162                .parse()
163                .unwrap();
164        let desc = Description::try_from(elem).unwrap();
165        assert_eq!(desc.media, "audio");
166        assert_eq!(desc.ssrc, None);
167    }
168}