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
7generate_element!(
8 /// Wrapper element describing an RTP session.
9 Description, "description", JINGLE_RTP,
10 attributes: [
11 /// Namespace of the encryption scheme used.
12 media: Required<String> = "media",
13
14 /// User-friendly name for the encryption scheme, should be `None` for OTR,
15 /// legacy OpenPGP and OX.
16 // XXX: is this a String or an u32?! Refer to RFC 3550.
17 ssrc: Option<String> = "ssrc",
18 ],
19 children: [
20 /// List of encodings that can be used for this RTP stream.
21 payload_types: Vec<PayloadType> = ("payload-type", JINGLE_RTP) => PayloadType
22
23 // TODO: Add support for <encryption/> and <bandwidth/>.
24 ]
25);
26
27generate_attribute!(
28 /// The number of channels.
29 Channels, "channels", u8, Default = 1
30);
31
32generate_element!(
33 /// An encoding that can be used for an RTP stream.
34 PayloadType, "payload-type", JINGLE_RTP,
35 attributes: [
36 /// The number of channels.
37 channels: Default<Channels> = "channels",
38
39 /// The sampling frequency in Hertz.
40 clockrate: Option<u32> = "clockrate",
41
42 /// The payload identifier.
43 id: Required<u8> = "id",
44
45 /// Maximum packet time as specified in RFC 4566.
46 maxptime: Option<u32> = "maxptime",
47
48 /// The appropriate subtype of the MIME type.
49 name: Option<String> = "name",
50
51 /// Packet time as specified in RFC 4566.
52 ptime: Option<u32> = "ptime",
53 ],
54 children: [
55 /// List of parameters specifying this payload-type.
56 ///
57 /// Their order MUST be ignored.
58 parameters: Vec<Parameter> = ("parameter", JINGLE_RTP) => Parameter
59 ]
60);
61
62generate_element!(
63 /// Parameter related to a payload.
64 Parameter, "parameter", JINGLE_RTP,
65 attributes: [
66 /// The name of the parameter, from the list at
67 /// https://www.iana.org/assignments/sdp-parameters/sdp-parameters.xhtml
68 name: Required<String> = "name",
69
70 /// The value of this parameter.
71 value: Required<String> = "value",
72 ]
73);
74
75#[cfg(test)]
76mod tests {
77 use super::*;
78 use minidom::Element;
79 use std::convert::TryFrom;
80
81 #[cfg(target_pointer_width = "32")]
82 #[test]
83 fn test_size() {
84 assert_size!(Description, 36);
85 assert_size!(Channels, 1);
86 assert_size!(PayloadType, 52);
87 assert_size!(Parameter, 24);
88 }
89
90 #[cfg(target_pointer_width = "64")]
91 #[test]
92 fn test_size() {
93 assert_size!(Description, 72);
94 assert_size!(Channels, 1);
95 assert_size!(PayloadType, 80);
96 assert_size!(Parameter, 48);
97 }
98
99 #[test]
100 fn test_simple() {
101 let elem: Element = "
102<description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'>
103 <payload-type xmlns='urn:xmpp:jingle:apps:rtp:1' channels='2' clockrate='48000' id='96' name='OPUS'/>
104 <payload-type xmlns='urn:xmpp:jingle:apps:rtp:1' channels='1' clockrate='32000' id='105' name='SPEEX'/>
105 <payload-type xmlns='urn:xmpp:jingle:apps:rtp:1' channels='1' clockrate='8000' id='9' name='G722'/>
106 <payload-type xmlns='urn:xmpp:jingle:apps:rtp:1' channels='1' clockrate='16000' id='106' name='SPEEX'/>
107 <payload-type xmlns='urn:xmpp:jingle:apps:rtp:1' clockrate='8000' id='8' name='PCMA'/>
108 <payload-type xmlns='urn:xmpp:jingle:apps:rtp:1' clockrate='8000' id='0' name='PCMU'/>
109 <payload-type xmlns='urn:xmpp:jingle:apps:rtp:1' channels='1' clockrate='8000' id='107' name='SPEEX'/>
110 <payload-type xmlns='urn:xmpp:jingle:apps:rtp:1' channels='1' clockrate='8000' id='99' name='AMR'>
111 <parameter xmlns='urn:xmpp:jingle:apps:rtp:1' name='octet-align' value='1'/>
112 <parameter xmlns='urn:xmpp:jingle:apps:rtp:1' name='crc' value='0'/>
113 <parameter xmlns='urn:xmpp:jingle:apps:rtp:1' name='robust-sorting' value='0'/>
114 <parameter xmlns='urn:xmpp:jingle:apps:rtp:1' name='interleaving' value='0'/>
115 </payload-type>
116 <payload-type xmlns='urn:xmpp:jingle:apps:rtp:1' clockrate='48000' id='100' name='telephone-event'>
117 <parameter xmlns='urn:xmpp:jingle:apps:rtp:1' name='events' value='0-15'/>
118 </payload-type>
119 <payload-type xmlns='urn:xmpp:jingle:apps:rtp:1' clockrate='16000' id='101' name='telephone-event'>
120 <parameter xmlns='urn:xmpp:jingle:apps:rtp:1' name='events' value='0-15'/>
121 </payload-type>
122 <payload-type xmlns='urn:xmpp:jingle:apps:rtp:1' clockrate='8000' id='102' name='telephone-event'>
123 <parameter xmlns='urn:xmpp:jingle:apps:rtp:1' name='events' value='0-15'/>
124 </payload-type>
125</description>"
126 .parse()
127 .unwrap();
128 let desc = Description::try_from(elem).unwrap();
129 assert_eq!(desc.media, "audio");
130 assert_eq!(desc.ssrc, None);
131 }
132}