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}