1extern crate url;
6use std::convert::TryFrom;
7use std::fmt;
8use std::fmt::Write;
9use std::iter;
10use std::str::FromStr;
11
12use error::SdpParserInternalError;
13use network::{parse_network_type, parse_unicast_address};
14use SdpType;
15
16use address::{Address, AddressType, ExplicitlyTypedAddress};
17use anonymizer::{AnonymizingClone, StatefulSdpAnonymizer};
18
19#[macro_export]
21macro_rules! option_to_string {
22 ($fmt_str:expr, $opt:expr) => {
23 match $opt {
24 Some(ref x) => format!($fmt_str, x),
25 None => "".to_string(),
26 }
27 };
28}
29
30#[macro_export]
31macro_rules! write_option_string {
32 ($f:expr, $fmt_str:expr, $opt:expr) => {
33 match $opt {
34 Some(ref x) => write!($f, $fmt_str, x),
35 None => Ok(()),
36 }
37 };
38}
39
40#[macro_export]
41macro_rules! maybe_vector_to_string {
42 ($fmt_str:expr, $vec:expr, $sep:expr) => {
43 match $vec.len() {
44 0 => "".to_string(),
45 _ => format!(
46 $fmt_str,
47 $vec.iter()
48 .map(ToString::to_string)
49 .collect::<Vec<String>>()
50 .join($sep)
51 ),
52 }
53 };
54}
55
56#[macro_export]
57macro_rules! non_empty_string_vec {
58 ( $( $x:expr ),* ) => {
59 {
60 let mut temp_vec = Vec::new();
61 $(
62 if !$x.is_empty() {
63 temp_vec.push($x);
64 }
65 )*
66 temp_vec
67 }
68 };
69}
70
71pub fn maybe_print_param<T>(name: &str, param: T, default_value: T) -> String
72where
73 T: PartialEq + ToString,
74{
75 if param != default_value {
76 name.to_owned() + ¶m.to_string()
77 } else {
78 "".to_string()
79 }
80}
81
82pub fn maybe_print_bool_param(name: &str, param: bool, default_value: bool) -> String {
83 if param != default_value {
84 name.to_owned() + "=" + &(param as i32).to_string()
85 } else {
86 "".to_string()
87 }
88}
89
90#[derive(Debug, Clone, PartialEq)]
91#[cfg_attr(feature = "serialize", derive(Serialize))]
92pub enum SdpSingleDirection {
93 Send = 1,
95 Recv = 2,
96}
97
98impl fmt::Display for SdpSingleDirection {
99 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
100 match *self {
101 SdpSingleDirection::Send => "send",
102 SdpSingleDirection::Recv => "recv",
103 }
104 .fmt(f)
105 }
106}
107
108#[derive(Debug, PartialEq, Clone)]
109#[cfg_attr(feature = "serialize", derive(Serialize))]
110pub enum SdpAttributePayloadType {
111 PayloadType(u8),
112 Wildcard, }
114
115impl fmt::Display for SdpAttributePayloadType {
116 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
117 match *self {
118 SdpAttributePayloadType::PayloadType(pt) => pt.fmt(f),
119 SdpAttributePayloadType::Wildcard => "*".fmt(f),
120 }
121 }
122}
123
124#[derive(Debug, Clone, PartialEq)]
125#[cfg_attr(feature = "serialize", derive(Serialize))]
126pub enum SdpAttributeCandidateTransport {
127 Udp,
128 Tcp,
129}
130
131impl fmt::Display for SdpAttributeCandidateTransport {
132 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
133 match *self {
134 SdpAttributeCandidateTransport::Udp => "UDP",
135 SdpAttributeCandidateTransport::Tcp => "TCP",
136 }
137 .fmt(f)
138 }
139}
140
141#[derive(Debug, Clone, PartialEq)]
142#[cfg_attr(feature = "serialize", derive(Serialize))]
143pub enum SdpAttributeCandidateType {
144 Host,
145 Srflx,
146 Prflx,
147 Relay,
148}
149
150impl fmt::Display for SdpAttributeCandidateType {
151 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
152 match *self {
153 SdpAttributeCandidateType::Host => "host",
154 SdpAttributeCandidateType::Srflx => "srflx",
155 SdpAttributeCandidateType::Prflx => "prflx",
156 SdpAttributeCandidateType::Relay => "relay",
157 }
158 .fmt(f)
159 }
160}
161
162#[derive(Debug, Clone, PartialEq)]
163#[cfg_attr(feature = "serialize", derive(Serialize))]
164pub enum SdpAttributeCandidateTcpType {
165 Active,
166 Passive,
167 Simultaneous,
168}
169
170impl fmt::Display for SdpAttributeCandidateTcpType {
171 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
172 match *self {
173 SdpAttributeCandidateTcpType::Active => "active",
174 SdpAttributeCandidateTcpType::Passive => "passive",
175 SdpAttributeCandidateTcpType::Simultaneous => "so",
176 }
177 .fmt(f)
178 }
179}
180
181#[derive(Clone)]
182#[cfg_attr(feature = "serialize", derive(Serialize))]
183#[cfg_attr(feature = "enhanced_debug", derive(Debug))]
184pub struct SdpAttributeCandidate {
185 pub foundation: String,
186 pub component: u32,
187 pub transport: SdpAttributeCandidateTransport,
188 pub priority: u64,
189 pub address: Address,
190 pub port: u32,
191 pub c_type: SdpAttributeCandidateType,
192 pub raddr: Option<Address>,
193 pub rport: Option<u32>,
194 pub tcp_type: Option<SdpAttributeCandidateTcpType>,
195 pub generation: Option<u32>,
196 pub ufrag: Option<String>,
197 pub networkcost: Option<u32>,
198 pub unknown_extensions: Vec<(String, String)>,
199}
200
201impl fmt::Display for SdpAttributeCandidate {
202 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
203 write!(
204 f,
205 "{foundation} {component} {transport} {priority} \
206 {address} {port} typ {ctype}\
207 {raddr}{rport}{tcp_type}{generation}{ufrag}{cost}\
208 {unknown}",
209 foundation = self.foundation,
210 component = self.component,
211 transport = self.transport,
212 priority = self.priority,
213 address = self.address,
214 port = self.port,
215 ctype = self.c_type,
216 raddr = option_to_string!(" raddr {}", self.raddr),
217 rport = option_to_string!(" rport {}", self.rport),
218 tcp_type = option_to_string!(" tcptype {}", self.tcp_type),
219 generation = option_to_string!(" generation {}", self.generation),
220 ufrag = option_to_string!(" ufrag {}", self.ufrag),
221 cost = option_to_string!(" network-cost {}", self.networkcost),
222 unknown =
223 self.unknown_extensions
224 .iter()
225 .fold(String::new(), |mut output, (name, value)| {
226 let _ = write!(output, " {name} {value}");
227 output
228 })
229 )
230 }
231}
232
233impl SdpAttributeCandidate {
234 pub fn new(
235 foundation: String,
236 component: u32,
237 transport: SdpAttributeCandidateTransport,
238 priority: u64,
239 address: Address,
240 port: u32,
241 c_type: SdpAttributeCandidateType,
242 ) -> SdpAttributeCandidate {
243 SdpAttributeCandidate {
244 foundation,
245 component,
246 transport,
247 priority,
248 address,
249 port,
250 c_type,
251 raddr: None,
252 rport: None,
253 tcp_type: None,
254 generation: None,
255 ufrag: None,
256 networkcost: None,
257 unknown_extensions: Vec::new(),
258 }
259 }
260
261 fn set_remote_address(&mut self, addr: Address) {
262 self.raddr = Some(addr)
263 }
264
265 fn set_remote_port(&mut self, p: u32) {
266 self.rport = Some(p)
267 }
268
269 fn set_tcp_type(&mut self, t: SdpAttributeCandidateTcpType) {
270 self.tcp_type = Some(t)
271 }
272
273 fn set_generation(&mut self, g: u32) {
274 self.generation = Some(g)
275 }
276
277 fn set_ufrag(&mut self, u: String) {
278 self.ufrag = Some(u)
279 }
280
281 fn set_network_cost(&mut self, n: u32) {
282 self.networkcost = Some(n)
283 }
284
285 fn add_unknown_extension(&mut self, name: String, value: String) {
286 self.unknown_extensions.push((name, value));
287 }
288}
289
290impl AnonymizingClone for SdpAttributeCandidate {
291 fn masked_clone(&self, anonymizer: &mut StatefulSdpAnonymizer) -> Self {
292 let mut masked = self.clone();
293 masked.address = anonymizer.mask_address(&self.address);
294 masked.port = anonymizer.mask_port(self.port);
295 masked.raddr = self
296 .raddr
297 .clone()
298 .map(|addr| anonymizer.mask_address(&addr));
299 masked.rport = self.rport.map(|port| anonymizer.mask_port(port));
300 masked
301 }
302}
303
304#[derive(Clone)]
305#[cfg_attr(feature = "serialize", derive(Serialize))]
306#[cfg_attr(feature = "enhanced_debug", derive(Debug))]
307pub enum SdpAttributeDtlsMessage {
308 Client(String),
309 Server(String),
310}
311
312impl fmt::Display for SdpAttributeDtlsMessage {
313 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
314 match self {
315 SdpAttributeDtlsMessage::Client(msg) => format!("client {msg}"),
316 SdpAttributeDtlsMessage::Server(msg) => format!("server {msg}"),
317 }
318 .fmt(f)
319 }
320}
321
322#[derive(Clone)]
323#[cfg_attr(feature = "serialize", derive(Serialize))]
324#[cfg_attr(feature = "enhanced_debug", derive(Debug))]
325pub struct SdpAttributeRemoteCandidate {
326 pub component: u32,
327 pub address: Address,
328 pub port: u32,
329}
330
331impl fmt::Display for SdpAttributeRemoteCandidate {
332 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
333 write!(
334 f,
335 "{component} {addr} {port}",
336 component = self.component,
337 addr = self.address,
338 port = self.port
339 )
340 }
341}
342
343impl AnonymizingClone for SdpAttributeRemoteCandidate {
344 fn masked_clone(&self, anon: &mut StatefulSdpAnonymizer) -> Self {
345 SdpAttributeRemoteCandidate {
346 address: anon.mask_address(&self.address),
347 port: anon.mask_port(self.port),
348 component: self.component,
349 }
350 }
351}
352
353#[derive(Clone)]
354#[cfg_attr(feature = "serialize", derive(Serialize))]
355#[cfg_attr(feature = "enhanced_debug", derive(Debug))]
356pub struct SdpAttributeSimulcastId {
357 pub id: String,
358 pub paused: bool,
359}
360
361impl SdpAttributeSimulcastId {
362 pub fn new(idstr: &str) -> SdpAttributeSimulcastId {
363 if let Some(idstr) = idstr.strip_prefix('~') {
364 SdpAttributeSimulcastId {
365 id: idstr.to_string(),
366 paused: true,
367 }
368 } else {
369 SdpAttributeSimulcastId {
370 id: idstr.to_string(),
371 paused: false,
372 }
373 }
374 }
375}
376
377impl fmt::Display for SdpAttributeSimulcastId {
378 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
379 if self.paused {
380 write!(f, "~")?;
381 }
382 self.id.fmt(f)
383 }
384}
385
386#[repr(C)]
387#[derive(Clone)]
388#[cfg_attr(feature = "serialize", derive(Serialize))]
389#[cfg_attr(feature = "enhanced_debug", derive(Debug))]
390pub struct SdpAttributeSimulcastVersion {
391 pub ids: Vec<SdpAttributeSimulcastId>,
392}
393
394impl SdpAttributeSimulcastVersion {
395 pub fn new(idlist: &str) -> SdpAttributeSimulcastVersion {
396 SdpAttributeSimulcastVersion {
397 ids: idlist
398 .split(',')
399 .map(SdpAttributeSimulcastId::new)
400 .collect(),
401 }
402 }
403}
404
405impl fmt::Display for SdpAttributeSimulcastVersion {
406 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
407 self.ids
408 .iter()
409 .map(ToString::to_string)
410 .collect::<Vec<String>>()
411 .join(",")
412 .fmt(f)
413 }
414}
415
416#[derive(Clone)]
417#[cfg_attr(feature = "serialize", derive(Serialize))]
418#[cfg_attr(feature = "enhanced_debug", derive(Debug))]
419pub struct SdpAttributeSimulcast {
420 pub send: Vec<SdpAttributeSimulcastVersion>,
421 pub receive: Vec<SdpAttributeSimulcastVersion>,
422}
423
424impl fmt::Display for SdpAttributeSimulcast {
425 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
426 non_empty_string_vec![
427 maybe_vector_to_string!("send {}", self.send, ";"),
428 maybe_vector_to_string!("recv {}", self.receive, ";")
429 ]
430 .join(" ")
431 .fmt(f)
432 }
433}
434
435#[derive(Clone)]
436#[cfg_attr(feature = "serialize", derive(Serialize))]
437#[cfg_attr(feature = "enhanced_debug", derive(Debug))]
438pub struct SdpAttributeRtcp {
439 pub port: u16,
440 pub unicast_addr: Option<ExplicitlyTypedAddress>,
441}
442
443impl SdpAttributeRtcp {
444 pub fn new(port: u16) -> SdpAttributeRtcp {
445 SdpAttributeRtcp {
446 port,
447 unicast_addr: None,
448 }
449 }
450
451 fn set_addr(&mut self, addr: ExplicitlyTypedAddress) {
452 self.unicast_addr = Some(addr)
453 }
454}
455
456impl fmt::Display for SdpAttributeRtcp {
457 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
458 match self.unicast_addr {
459 Some(ref addr) => write!(f, "{} {}", self.port, addr),
460 None => self.port.fmt(f),
461 }
462 }
463}
464
465#[derive(Clone)]
466#[cfg_attr(feature = "serialize", derive(Serialize))]
467#[cfg_attr(feature = "enhanced_debug", derive(Debug))]
468pub enum SdpAttributeRtcpFbType {
469 Ack = 0,
470 Ccm = 2, Nack,
474 TrrInt,
475 Remb,
476 TransCc,
477}
478
479impl fmt::Display for SdpAttributeRtcpFbType {
480 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
481 match *self {
482 SdpAttributeRtcpFbType::Ack => "ack",
483 SdpAttributeRtcpFbType::Ccm => "ccm",
484 SdpAttributeRtcpFbType::Nack => "nack",
485 SdpAttributeRtcpFbType::TrrInt => "trr-int",
486 SdpAttributeRtcpFbType::Remb => "goog-remb",
487 SdpAttributeRtcpFbType::TransCc => "transport-cc",
488 }
489 .fmt(f)
490 }
491}
492
493#[derive(Clone)]
494#[cfg_attr(feature = "serialize", derive(Serialize))]
495#[cfg_attr(feature = "enhanced_debug", derive(Debug))]
496pub struct SdpAttributeRtcpFb {
497 pub payload_type: SdpAttributePayloadType,
498 pub feedback_type: SdpAttributeRtcpFbType,
499 pub parameter: String,
500 pub extra: String,
501}
502
503impl fmt::Display for SdpAttributeRtcpFb {
504 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
505 write!(f, "{} {}", self.payload_type, self.feedback_type,)?;
506 if !self.parameter.is_empty() {
507 write!(
508 f,
509 " {}{}",
510 self.parameter,
511 maybe_print_param(" ", self.extra.clone(), "".to_string()),
512 )?;
513 }
514 Ok(())
515 }
516}
517
518#[derive(Clone)]
519#[cfg_attr(feature = "serialize", derive(Serialize))]
520#[cfg_attr(feature = "enhanced_debug", derive(Debug))]
521pub enum SdpAttributeDirection {
522 Recvonly,
523 Sendonly,
524 Sendrecv,
525}
526
527impl fmt::Display for SdpAttributeDirection {
528 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
529 match *self {
530 SdpAttributeDirection::Recvonly => "recvonly",
531 SdpAttributeDirection::Sendonly => "sendonly",
532 SdpAttributeDirection::Sendrecv => "sendrecv",
533 }
534 .fmt(f)
535 }
536}
537
538#[derive(Clone)]
539#[cfg_attr(feature = "serialize", derive(Serialize))]
540#[cfg_attr(feature = "enhanced_debug", derive(Debug))]
541pub struct SdpAttributeExtmap {
542 pub id: u16,
543 pub direction: Option<SdpAttributeDirection>,
544 pub url: String,
545 pub extension_attributes: Option<String>,
546}
547
548impl fmt::Display for SdpAttributeExtmap {
549 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
550 write!(
551 f,
552 "{id}{direction} {url}{ext}",
553 id = self.id,
554 direction = option_to_string!("/{}", self.direction),
555 url = self.url,
556 ext = option_to_string!(" {}", self.extension_attributes)
557 )
558 }
559}
560
561#[derive(Clone, Copy)]
562#[cfg_attr(feature = "serialize", derive(Serialize))]
563#[cfg_attr(feature = "enhanced_debug", derive(Debug))]
564pub struct RtxFmtpParameters {
565 pub apt: u8,
566 pub rtx_time: Option<u32>,
567}
568
569impl fmt::Display for RtxFmtpParameters {
570 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
571 if let Some(rtx_time) = self.rtx_time {
572 write!(f, "apt={};rtx-time={}", self.apt, rtx_time)
573 } else {
574 write!(f, "apt={}", self.apt)
575 }
576 }
577}
578
579#[derive(Clone)]
580#[cfg_attr(feature = "serialize", derive(Serialize))]
581#[cfg_attr(feature = "enhanced_debug", derive(Debug))]
582pub struct SdpAttributeFmtpParameters {
583 pub packetization_mode: u32,
588 pub level_asymmetry_allowed: bool,
589 pub profile_level_id: u32,
590 pub max_fs: u32,
591 pub max_cpb: u32,
592 pub max_dpb: u32,
593 pub max_br: u32,
594 pub max_mbps: u32,
595
596 pub max_fr: u32,
599
600 pub profile: Option<u8>,
608 pub level_idx: Option<u8>,
612 pub tier: Option<u8>,
616
617 pub maxplaybackrate: u32,
619 pub maxaveragebitrate: u32,
620 pub usedtx: bool,
621 pub stereo: bool,
622 pub useinbandfec: bool,
623 pub cbr: bool,
624 pub ptime: u32,
625 pub minptime: u32,
626 pub maxptime: u32,
627
628 pub encodings: Vec<u8>,
630
631 pub dtmf_tones: String,
633
634 pub rtx: Option<RtxFmtpParameters>,
636
637 pub unknown_tokens: Vec<String>,
639}
640
641impl fmt::Display for SdpAttributeFmtpParameters {
642 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
643 if let Some(ref rtx) = self.rtx {
644 return write!(f, "{rtx}");
646 }
647 if !self.dtmf_tones.is_empty() {
648 return write!(f, "{}", self.dtmf_tones);
650 } else if !self.encodings.is_empty() {
651 return self
653 .encodings
654 .iter()
655 .map(ToString::to_string)
656 .collect::<Vec<String>>()
657 .join("/")
658 .fmt(f);
659 };
660 write!(
661 f,
662 "{}",
663 non_empty_string_vec![
664 maybe_print_param(
665 "profile-level-id=",
666 format!("{:06x}", self.profile_level_id),
667 "420010".to_string()
668 ),
669 maybe_print_bool_param(
670 "level-asymmetry-allowed",
671 self.level_asymmetry_allowed,
672 false
673 ),
674 maybe_print_param("packetization-mode=", self.packetization_mode, 0),
675 maybe_print_param("max-fs=", self.max_fs, 0),
676 maybe_print_param("max-cpb=", self.max_cpb, 0),
677 maybe_print_param("max-dpb=", self.max_dpb, 0),
678 maybe_print_param("max-br=", self.max_br, 0),
679 maybe_print_param("max-mbps=", self.max_mbps, 0),
680 maybe_print_param("max-fr=", self.max_fr, 0),
681 match self.profile {
682 Some(profile) => format!("profile={}", profile),
683 None => "".to_string(),
684 },
685 match self.level_idx {
686 Some(level_idx) => format!("level-idx={}", level_idx),
687 None => "".to_string(),
688 },
689 match self.tier {
690 Some(tier) => format!("tier={}", tier),
691 None => "".to_string(),
692 },
693 maybe_print_param("maxplaybackrate=", self.maxplaybackrate, 48000),
694 maybe_print_param("maxaveragebitrate=", self.maxaveragebitrate, 0),
695 maybe_print_param("ptime=", self.ptime, 0),
696 maybe_print_param("minptime=", self.minptime, 0),
697 maybe_print_param("maxptime=", self.maxptime, 0),
698 maybe_print_bool_param("usedtx", self.usedtx, false),
699 maybe_print_bool_param("stereo", self.stereo, false),
700 maybe_print_bool_param("useinbandfec", self.useinbandfec, false),
701 maybe_print_bool_param("cbr", self.cbr, false),
702 maybe_vector_to_string!("{}", self.unknown_tokens, ",")
703 ]
704 .join(";")
705 )
706 }
707}
708
709#[derive(Clone)]
710#[cfg_attr(feature = "serialize", derive(Serialize))]
711#[cfg_attr(feature = "enhanced_debug", derive(Debug))]
712pub struct SdpAttributeFmtp {
713 pub payload_type: u8,
714 pub parameters: SdpAttributeFmtpParameters,
715}
716
717impl fmt::Display for SdpAttributeFmtp {
718 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
719 write!(
720 f,
721 "{pt} {parameter}",
722 pt = self.payload_type,
723 parameter = self.parameters
724 )
725 }
726}
727
728#[derive(Clone, Copy, PartialEq, Eq)]
729#[cfg_attr(feature = "serialize", derive(Serialize))]
730#[cfg_attr(feature = "enhanced_debug", derive(Debug))]
731pub enum SdpAttributeFingerprintHashType {
732 Sha1,
733 Sha224,
734 Sha256,
735 Sha384,
736 Sha512,
737}
738
739impl SdpAttributeFingerprintHashType {
740 pub fn try_from_name(name: &str) -> Result<Self, SdpParserInternalError> {
741 match name {
742 "sha-1" => Ok(Self::Sha1),
743 "sha-224" => Ok(Self::Sha224),
744 "sha-256" => Ok(Self::Sha256),
745 "sha-384" => Ok(Self::Sha384),
746 "sha-512" => Ok(Self::Sha512),
747 unknown => Err(SdpParserInternalError::Unsupported(format!(
748 "fingerprint contains an unsupported hash algorithm '{unknown}'"
749 ))),
750 }
751 }
752 pub fn octet_count(&self) -> usize {
753 match self {
754 Self::Sha1 => 20,
755 Self::Sha224 => 28,
756 Self::Sha256 => 32,
757 Self::Sha384 => 48,
758 Self::Sha512 => 64,
759 }
760 }
761
762 pub fn parse_octets(&self, octets_string: &str) -> Result<Vec<u8>, SdpParserInternalError> {
763 let bytes = octets_string
764 .split(':')
765 .map(|byte_token| {
766 if byte_token.len() != 2 {
767 return Err(SdpParserInternalError::Generic(
768 "fingerpint's byte tokens must have 2 hexdigits".to_string(),
769 ));
770 }
771 Ok(u8::from_str_radix(byte_token, 16)?)
772 })
773 .collect::<Result<Vec<u8>, _>>()?;
774
775 if bytes.len() != self.octet_count() {
776 return Err(SdpParserInternalError::Generic(format!(
777 "fingerprint has {} bytes but should have {} bytes",
778 bytes.len(),
779 self.octet_count(),
780 )));
781 }
782
783 Ok(bytes)
784 }
785}
786
787impl fmt::Display for SdpAttributeFingerprintHashType {
788 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
789 match *self {
790 SdpAttributeFingerprintHashType::Sha1 => "sha-1",
791 SdpAttributeFingerprintHashType::Sha224 => "sha-224",
792 SdpAttributeFingerprintHashType::Sha256 => "sha-256",
793 SdpAttributeFingerprintHashType::Sha384 => "sha-384",
794 SdpAttributeFingerprintHashType::Sha512 => "sha-512",
795 }
796 .fmt(f)
797 }
798}
799
800#[derive(Clone, PartialEq, Eq)]
801#[cfg_attr(feature = "serialize", derive(Serialize))]
802#[cfg_attr(feature = "enhanced_debug", derive(Debug))]
803pub struct SdpAttributeFingerprint {
804 pub hash_algorithm: SdpAttributeFingerprintHashType,
805 pub fingerprint: Vec<u8>,
806}
807
808impl TryFrom<(SdpAttributeFingerprintHashType, Vec<u8>)> for SdpAttributeFingerprint {
809 type Error = SdpParserInternalError;
810 fn try_from(
811 parts: (SdpAttributeFingerprintHashType, Vec<u8>),
812 ) -> Result<Self, SdpParserInternalError> {
813 let (hash_algorithm, fingerprint) = parts;
814 match (hash_algorithm.octet_count(), fingerprint.len()) {
815 (a, b) if a == b => Ok(Self {
816 hash_algorithm,
817 fingerprint,
818 }),
819 (a, b) => Err(SdpParserInternalError::Generic(format!(
820 "Hash algoritm expects {a} fingerprint bytes not {b}",
821 ))),
822 }
823 }
824}
825
826impl fmt::Display for SdpAttributeFingerprint {
827 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
828 write!(
829 f,
830 "{hash} {fp}",
831 hash = self.hash_algorithm,
832 fp = self
833 .fingerprint
834 .iter()
835 .map(|byte| format!("{byte:02X}"))
836 .collect::<Vec<String>>()
837 .join(":")
838 )
839 }
840}
841
842impl AnonymizingClone for SdpAttributeFingerprint {
843 fn masked_clone(&self, anon: &mut StatefulSdpAnonymizer) -> Self {
844 SdpAttributeFingerprint {
845 hash_algorithm: self.hash_algorithm,
846 fingerprint: anon.mask_cert_finger_print(&self.fingerprint),
847 }
848 }
849}
850
851fn imageattr_discrete_value_list_to_string<T>(values: &[T]) -> String
852where
853 T: ToString,
854{
855 match values.len() {
856 1 => values[0].to_string(),
857 _ => format!(
858 "[{}]",
859 values
860 .iter()
861 .map(ToString::to_string)
862 .collect::<Vec<String>>()
863 .join(",")
864 ),
865 }
866}
867
868#[derive(Debug, PartialEq, Clone)]
869#[cfg_attr(feature = "serialize", derive(Serialize))]
870pub enum SdpAttributeImageAttrXyRange {
871 Range(u32, u32, Option<u32>), DiscreteValues(Vec<u32>),
873}
874
875impl fmt::Display for SdpAttributeImageAttrXyRange {
876 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
877 match *self {
878 SdpAttributeImageAttrXyRange::Range(ref min, ref max, ref step_opt) => {
879 write!(f, "[{min}:")?;
880 if step_opt.is_some() {
881 write!(f, "{}:", step_opt.unwrap())?;
882 }
883 write!(f, "{max}]")
884 }
885 SdpAttributeImageAttrXyRange::DiscreteValues(ref values) => {
886 write!(f, "{}", imageattr_discrete_value_list_to_string(values))
887 }
888 }
889 }
890}
891
892#[derive(Debug, PartialEq, Clone)]
893#[cfg_attr(feature = "serialize", derive(Serialize))]
894pub enum SdpAttributeImageAttrSRange {
895 Range(f32, f32), DiscreteValues(Vec<f32>),
897}
898
899impl fmt::Display for SdpAttributeImageAttrSRange {
900 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
901 match self {
902 SdpAttributeImageAttrSRange::Range(min, max) => write!(f, "[{min}-{max}]"),
903 SdpAttributeImageAttrSRange::DiscreteValues(values) => {
904 write!(f, "{}", imageattr_discrete_value_list_to_string(values))
905 }
906 }
907 }
908}
909
910#[derive(Debug, PartialEq, Clone)]
911#[cfg_attr(feature = "serialize", derive(Serialize))]
912pub struct SdpAttributeImageAttrPRange {
913 pub min: f32,
914 pub max: f32,
915}
916
917impl fmt::Display for SdpAttributeImageAttrPRange {
918 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
919 write!(f, "[{}-{}]", self.min, self.max)
920 }
921}
922
923#[derive(Debug, PartialEq, Clone)]
924#[cfg_attr(feature = "serialize", derive(Serialize))]
925pub struct SdpAttributeImageAttrSet {
926 pub x: SdpAttributeImageAttrXyRange,
927 pub y: SdpAttributeImageAttrXyRange,
928 pub sar: Option<SdpAttributeImageAttrSRange>,
929 pub par: Option<SdpAttributeImageAttrPRange>,
930 pub q: Option<f32>,
931}
932
933impl fmt::Display for SdpAttributeImageAttrSet {
934 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
935 write!(f, "[x={x},y={y}", x = self.x, y = self.y)?;
936 write_option_string!(f, ",sar={}", self.sar)?;
937 write_option_string!(f, ",par={}", self.par)?;
938 write_option_string!(f, ",q={}", self.q)?;
939 write!(f, "]")
940 }
941}
942
943#[derive(Debug, PartialEq, Clone)]
944#[cfg_attr(feature = "serialize", derive(Serialize))]
945pub enum SdpAttributeImageAttrSetList {
946 Sets(Vec<SdpAttributeImageAttrSet>),
947 Wildcard,
948}
949
950impl fmt::Display for SdpAttributeImageAttrSetList {
951 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
952 match *self {
953 SdpAttributeImageAttrSetList::Sets(ref sets) => sets
954 .iter()
955 .map(ToString::to_string)
956 .collect::<Vec<String>>()
957 .join(" ")
958 .fmt(f),
959 SdpAttributeImageAttrSetList::Wildcard => "*".fmt(f),
960 }
961 }
962}
963
964#[derive(Clone)]
965#[cfg_attr(feature = "serialize", derive(Serialize))]
966#[cfg_attr(feature = "enhanced_debug", derive(Debug))]
967pub struct SdpAttributeImageAttr {
968 pub pt: SdpAttributePayloadType,
969 pub send: SdpAttributeImageAttrSetList,
970 pub recv: SdpAttributeImageAttrSetList,
971}
972
973impl fmt::Display for SdpAttributeImageAttr {
974 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
975 let maybe_sets_to_string = |set_list| match set_list {
976 SdpAttributeImageAttrSetList::Sets(sets) => match sets.len() {
977 0 => None,
978 _ => Some(SdpAttributeImageAttrSetList::Sets(sets)),
979 },
980 x => Some(x),
981 };
982 self.pt.fmt(f)?;
983 write_option_string!(f, " send {}", maybe_sets_to_string(self.send.clone()))?;
984 write_option_string!(f, " recv {}", maybe_sets_to_string(self.recv.clone()))
985 }
986}
987
988#[derive(Clone)]
989#[cfg_attr(feature = "serialize", derive(Serialize))]
990#[cfg_attr(feature = "enhanced_debug", derive(Debug))]
991pub struct SdpAttributeSctpmap {
992 pub port: u16,
993 pub channels: u32,
994}
995
996impl fmt::Display for SdpAttributeSctpmap {
997 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
998 write!(
999 f,
1000 "{port} webrtc-datachannel {channels}",
1001 port = self.port,
1002 channels = self.channels
1003 )
1004 }
1005}
1006
1007#[derive(Clone)]
1008#[cfg_attr(feature = "serialize", derive(Serialize))]
1009#[cfg_attr(feature = "enhanced_debug", derive(Debug))]
1010pub enum SdpAttributeGroupSemantic {
1011 LipSynchronization, FlowIdentification, SingleReservationFlow, AlternateNetworkAddressType, ForwardErrorCorrection, DecodingDependency, Bundle, }
1019
1020impl fmt::Display for SdpAttributeGroupSemantic {
1021 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1022 match *self {
1023 SdpAttributeGroupSemantic::LipSynchronization => "LS",
1024 SdpAttributeGroupSemantic::FlowIdentification => "FID",
1025 SdpAttributeGroupSemantic::SingleReservationFlow => "SRF",
1026 SdpAttributeGroupSemantic::AlternateNetworkAddressType => "ANAT",
1027 SdpAttributeGroupSemantic::ForwardErrorCorrection => "FEC",
1028 SdpAttributeGroupSemantic::DecodingDependency => "DDP",
1029 SdpAttributeGroupSemantic::Bundle => "BUNDLE",
1030 }
1031 .fmt(f)
1032 }
1033}
1034
1035#[derive(Clone)]
1036#[cfg_attr(feature = "serialize", derive(Serialize))]
1037#[cfg_attr(feature = "enhanced_debug", derive(Debug))]
1038pub struct SdpAttributeGroup {
1039 pub semantics: SdpAttributeGroupSemantic,
1040 pub tags: Vec<String>,
1041}
1042
1043impl fmt::Display for SdpAttributeGroup {
1044 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1045 write!(
1046 f,
1047 "{}{}",
1048 self.semantics,
1049 maybe_vector_to_string!(" {}", self.tags, " ")
1050 )
1051 }
1052}
1053
1054#[derive(Clone)]
1055#[cfg_attr(feature = "serialize", derive(Serialize))]
1056#[cfg_attr(feature = "enhanced_debug", derive(Debug))]
1057pub struct SdpAttributeMsid {
1058 pub id: String,
1059 pub appdata: Option<String>,
1060}
1061
1062impl fmt::Display for SdpAttributeMsid {
1063 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1064 self.id.fmt(f)?;
1065 write_option_string!(f, " {}", self.appdata)
1066 }
1067}
1068
1069#[derive(Clone, Debug)]
1070#[cfg_attr(feature = "serialize", derive(Serialize))]
1071pub struct SdpAttributeMsidSemantic {
1072 pub semantic: String,
1073 pub msids: Vec<String>,
1074}
1075
1076impl fmt::Display for SdpAttributeMsidSemantic {
1077 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1078 write!(f, "{} ", self.semantic)?;
1079 match self.msids.len() {
1080 0 => "*".fmt(f),
1081 _ => self.msids.join(" ").fmt(f),
1082 }
1083 }
1084}
1085
1086#[derive(Clone)]
1087#[cfg_attr(feature = "serialize", derive(Serialize))]
1088#[cfg_attr(feature = "enhanced_debug", derive(Debug))]
1089pub struct SdpAttributeRidParameters {
1090 pub max_width: u32,
1091 pub max_height: u32,
1092 pub max_fps: u32,
1093 pub max_fs: u32,
1094 pub max_br: u32,
1095 pub max_pps: u32,
1096
1097 pub unknown: Vec<String>,
1098}
1099
1100impl fmt::Display for SdpAttributeRidParameters {
1101 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1102 non_empty_string_vec![
1103 maybe_print_param("max-width=", self.max_width, 0),
1104 maybe_print_param("max-height=", self.max_height, 0),
1105 maybe_print_param("max-fps=", self.max_fps, 0),
1106 maybe_print_param("max-fs=", self.max_fs, 0),
1107 maybe_print_param("max-br=", self.max_br, 0),
1108 maybe_print_param("max-pps=", self.max_pps, 0),
1109 maybe_vector_to_string!("{}", self.unknown, ";")
1110 ]
1111 .join(";")
1112 .fmt(f)
1113 }
1114}
1115
1116#[derive(Clone)]
1117#[cfg_attr(feature = "serialize", derive(Serialize))]
1118#[cfg_attr(feature = "enhanced_debug", derive(Debug))]
1119pub struct SdpAttributeRid {
1120 pub id: String,
1121 pub direction: SdpSingleDirection,
1122 pub formats: Vec<u16>,
1123 pub params: SdpAttributeRidParameters,
1124 pub depends: Vec<String>,
1125}
1126
1127impl fmt::Display for SdpAttributeRid {
1128 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1129 write!(
1130 f,
1131 "{id} {direction}{format}",
1132 id = self.id,
1133 direction = self.direction,
1134 format = match non_empty_string_vec![
1135 maybe_vector_to_string!("pt={}", self.formats, ","),
1136 self.params.to_string(),
1137 maybe_vector_to_string!("depends={}", self.depends, ",")
1138 ]
1139 .join(";")
1140 .as_str()
1141 {
1142 "" => "".to_string(),
1143 x => format!(" {x}"),
1144 }
1145 )
1146 }
1147}
1148
1149#[derive(Clone)]
1150#[cfg_attr(feature = "serialize", derive(Serialize))]
1151#[cfg_attr(feature = "enhanced_debug", derive(Debug))]
1152pub struct SdpAttributeRtpmap {
1153 pub payload_type: u8,
1154 pub codec_name: String,
1155 pub frequency: u32,
1156 pub channels: Option<u32>,
1157}
1158
1159impl SdpAttributeRtpmap {
1160 pub fn new(payload_type: u8, codec_name: String, frequency: u32) -> SdpAttributeRtpmap {
1161 SdpAttributeRtpmap {
1162 payload_type,
1163 codec_name,
1164 frequency,
1165 channels: None,
1166 }
1167 }
1168
1169 fn set_channels(&mut self, c: u32) {
1170 self.channels = Some(c)
1171 }
1172}
1173
1174impl fmt::Display for SdpAttributeRtpmap {
1175 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1176 write!(
1177 f,
1178 "{pt} {name}/{freq}",
1179 pt = self.payload_type,
1180 name = self.codec_name,
1181 freq = self.frequency
1182 )?;
1183 write_option_string!(f, "/{}", self.channels)
1184 }
1185}
1186
1187#[derive(Clone)]
1188#[cfg_attr(feature = "serialize", derive(Serialize))]
1189#[cfg_attr(feature = "enhanced_debug", derive(Debug))]
1190pub enum SdpAttributeSetup {
1191 Active,
1192 Actpass,
1193 Holdconn,
1194 Passive,
1195}
1196
1197impl fmt::Display for SdpAttributeSetup {
1198 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1199 match *self {
1200 SdpAttributeSetup::Active => "active",
1201 SdpAttributeSetup::Actpass => "actpass",
1202 SdpAttributeSetup::Holdconn => "holdconn",
1203 SdpAttributeSetup::Passive => "passive",
1204 }
1205 .fmt(f)
1206 }
1207}
1208
1209#[derive(Clone)]
1210#[cfg_attr(feature = "serialize", derive(Serialize))]
1211#[cfg_attr(feature = "enhanced_debug", derive(Debug))]
1212pub struct SdpAttributeSsrc {
1213 pub id: u32,
1214 pub attribute: Option<String>,
1215 pub value: Option<String>,
1216}
1217
1218impl SdpAttributeSsrc {
1219 pub fn new(id: u32) -> SdpAttributeSsrc {
1220 SdpAttributeSsrc {
1221 id,
1222 attribute: None,
1223 value: None,
1224 }
1225 }
1226
1227 fn set_attribute(&mut self, a: &str) {
1228 if a.find(':').is_none() {
1229 self.attribute = Some(a.to_string());
1230 } else {
1231 let v: Vec<&str> = a.splitn(2, ':').collect();
1232 self.attribute = Some(v[0].to_string());
1233 self.value = Some(v[1].to_string());
1234 }
1235 }
1236}
1237
1238impl fmt::Display for SdpAttributeSsrc {
1239 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1240 self.id.fmt(f)?;
1241 write_option_string!(f, " {}", self.attribute)?;
1242 write_option_string!(f, ":{}", self.value)
1243 }
1244}
1245
1246impl AnonymizingClone for SdpAttributeSsrc {
1247 fn masked_clone(&self, anon: &mut StatefulSdpAnonymizer) -> Self {
1248 Self {
1249 id: self.id,
1250 attribute: self.attribute.clone(),
1251 value: self.attribute.as_ref().and_then(|attribute| {
1252 match (attribute.to_lowercase().as_str(), &self.value) {
1253 ("cname", Some(ref cname)) => Some(anon.mask_cname(cname.as_str())),
1254 (_, Some(_)) => self.value.clone(),
1255 (_, None) => None,
1256 }
1257 }),
1258 }
1259 }
1260}
1261
1262#[derive(Clone)]
1263#[cfg_attr(feature = "serialize", derive(Serialize))]
1264#[cfg_attr(feature = "enhanced_debug", derive(Debug))]
1265pub enum SdpSsrcGroupSemantic {
1266 Duplication, FlowIdentification, ForwardErrorCorrection, ForwardErrorCorrectionFr, Sim, }
1272
1273impl fmt::Display for SdpSsrcGroupSemantic {
1274 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1275 match *self {
1276 SdpSsrcGroupSemantic::Duplication => "DUP",
1277 SdpSsrcGroupSemantic::FlowIdentification => "FID",
1278 SdpSsrcGroupSemantic::ForwardErrorCorrection => "FEC",
1279 SdpSsrcGroupSemantic::ForwardErrorCorrectionFr => "FEC-FR",
1280 SdpSsrcGroupSemantic::Sim => "SIM",
1281 }
1282 .fmt(f)
1283 }
1284}
1285
1286#[derive(Clone)]
1287#[cfg_attr(feature = "serialize", derive(Serialize))]
1288#[cfg_attr(feature = "enhanced_debug", derive(Debug))]
1289pub enum SdpAttribute {
1290 BundleOnly,
1291 Candidate(SdpAttributeCandidate),
1292 DtlsMessage(SdpAttributeDtlsMessage),
1293 EndOfCandidates,
1294 Extmap(SdpAttributeExtmap),
1295 ExtmapAllowMixed,
1296 Fingerprint(SdpAttributeFingerprint),
1297 Fmtp(SdpAttributeFmtp),
1298 FrameRate(f64),
1299 Group(SdpAttributeGroup),
1300 IceLite,
1301 IceMismatch,
1302 IceOptions(Vec<String>),
1303 IcePacing(u64),
1304 IcePwd(String),
1305 IceUfrag(String),
1306 Identity(String),
1307 ImageAttr(SdpAttributeImageAttr),
1308 Inactive,
1309 Label(String),
1310 MaxMessageSize(u64),
1311 MaxPtime(u64),
1312 Mid(String),
1313 Msid(SdpAttributeMsid),
1314 MsidSemantic(SdpAttributeMsidSemantic),
1315 Ptime(u64),
1316 Rid(SdpAttributeRid),
1317 Recvonly,
1318 RemoteCandidate(SdpAttributeRemoteCandidate),
1319 Rtpmap(SdpAttributeRtpmap),
1320 Rtcp(SdpAttributeRtcp),
1321 Rtcpfb(SdpAttributeRtcpFb),
1322 RtcpMux,
1323 RtcpMuxOnly, RtcpRsize,
1325 Sctpmap(SdpAttributeSctpmap),
1326 SctpPort(u64),
1327 Sendonly,
1328 Sendrecv,
1329 Setup(SdpAttributeSetup),
1330 Simulcast(SdpAttributeSimulcast),
1331 Ssrc(SdpAttributeSsrc),
1332 SsrcGroup(SdpSsrcGroupSemantic, Vec<SdpAttributeSsrc>),
1333}
1334
1335impl SdpAttribute {
1336 pub fn allowed_at_session_level(&self) -> bool {
1337 match *self {
1338 SdpAttribute::BundleOnly
1339 | SdpAttribute::Candidate(..)
1340 | SdpAttribute::Fmtp(..)
1341 | SdpAttribute::FrameRate(..)
1342 | SdpAttribute::IceMismatch
1343 | SdpAttribute::ImageAttr(..)
1344 | SdpAttribute::Label(..)
1345 | SdpAttribute::MaxMessageSize(..)
1346 | SdpAttribute::MaxPtime(..)
1347 | SdpAttribute::Mid(..)
1348 | SdpAttribute::Msid(..)
1349 | SdpAttribute::Ptime(..)
1350 | SdpAttribute::Rid(..)
1351 | SdpAttribute::RemoteCandidate(..)
1352 | SdpAttribute::Rtpmap(..)
1353 | SdpAttribute::Rtcp(..)
1354 | SdpAttribute::Rtcpfb(..)
1355 | SdpAttribute::RtcpMux
1356 | SdpAttribute::RtcpMuxOnly
1357 | SdpAttribute::RtcpRsize
1358 | SdpAttribute::Sctpmap(..)
1359 | SdpAttribute::SctpPort(..)
1360 | SdpAttribute::Simulcast(..)
1361 | SdpAttribute::Ssrc(..)
1362 | SdpAttribute::SsrcGroup(..) => false,
1363
1364 SdpAttribute::DtlsMessage { .. }
1365 | SdpAttribute::EndOfCandidates
1366 | SdpAttribute::Extmap(..)
1367 | SdpAttribute::ExtmapAllowMixed
1368 | SdpAttribute::Fingerprint(..)
1369 | SdpAttribute::Group(..)
1370 | SdpAttribute::IceLite
1371 | SdpAttribute::IceOptions(..)
1372 | SdpAttribute::IcePacing(..)
1373 | SdpAttribute::IcePwd(..)
1374 | SdpAttribute::IceUfrag(..)
1375 | SdpAttribute::Identity(..)
1376 | SdpAttribute::Inactive
1377 | SdpAttribute::MsidSemantic(..)
1378 | SdpAttribute::Recvonly
1379 | SdpAttribute::Sendonly
1380 | SdpAttribute::Sendrecv
1381 | SdpAttribute::Setup(..) => true,
1382 }
1383 }
1384
1385 pub fn allowed_at_media_level(&self) -> bool {
1386 match *self {
1387 SdpAttribute::DtlsMessage { .. }
1388 | SdpAttribute::Group(..)
1389 | SdpAttribute::IceLite
1390 | SdpAttribute::IcePacing(..)
1391 | SdpAttribute::Identity(..)
1392 | SdpAttribute::MsidSemantic(..) => false,
1393
1394 SdpAttribute::BundleOnly
1395 | SdpAttribute::Candidate(..)
1396 | SdpAttribute::EndOfCandidates
1397 | SdpAttribute::Extmap(..)
1398 | SdpAttribute::ExtmapAllowMixed
1399 | SdpAttribute::Fingerprint(..)
1400 | SdpAttribute::Fmtp(..)
1401 | SdpAttribute::FrameRate(..)
1402 | SdpAttribute::IceMismatch
1403 | SdpAttribute::IceOptions(..)
1404 | SdpAttribute::IcePwd(..)
1405 | SdpAttribute::IceUfrag(..)
1406 | SdpAttribute::ImageAttr(..)
1407 | SdpAttribute::Inactive
1408 | SdpAttribute::Label(..)
1409 | SdpAttribute::MaxMessageSize(..)
1410 | SdpAttribute::MaxPtime(..)
1411 | SdpAttribute::Mid(..)
1412 | SdpAttribute::Msid(..)
1413 | SdpAttribute::Ptime(..)
1414 | SdpAttribute::Rid(..)
1415 | SdpAttribute::Recvonly
1416 | SdpAttribute::RemoteCandidate(..)
1417 | SdpAttribute::Rtpmap(..)
1418 | SdpAttribute::Rtcp(..)
1419 | SdpAttribute::Rtcpfb(..)
1420 | SdpAttribute::RtcpMux
1421 | SdpAttribute::RtcpMuxOnly
1422 | SdpAttribute::RtcpRsize
1423 | SdpAttribute::Sctpmap(..)
1424 | SdpAttribute::SctpPort(..)
1425 | SdpAttribute::Sendonly
1426 | SdpAttribute::Sendrecv
1427 | SdpAttribute::Setup(..)
1428 | SdpAttribute::Simulcast(..)
1429 | SdpAttribute::Ssrc(..)
1430 | SdpAttribute::SsrcGroup(..) => true,
1431 }
1432 }
1433}
1434
1435impl FromStr for SdpAttribute {
1436 type Err = SdpParserInternalError;
1437
1438 fn from_str(line: &str) -> Result<Self, Self::Err> {
1439 let tokens: Vec<_> = line.splitn(2, ':').collect();
1440 let name = tokens[0].to_lowercase();
1441 let val = match tokens.get(1) {
1442 Some(x) => x.trim(),
1443 None => "",
1444 };
1445 if tokens.len() > 1 {
1446 match name.as_str() {
1447 "bundle-only" | "end-of-candidates" | "extmap-allow-mixed" | "ice-lite"
1448 | "ice-mismatch" | "inactive" | "recvonly" | "rtcp-mux" | "rtcp-mux-only"
1449 | "rtcp-rsize" | "sendonly" | "sendrecv" => {
1450 return Err(SdpParserInternalError::Generic(format!(
1451 "{name} attribute is not allowed to have a value",
1452 )));
1453 }
1454 _ => (),
1455 }
1456 }
1457 match name.as_str() {
1458 "bundle-only" => Ok(SdpAttribute::BundleOnly),
1459 "dtls-message" => parse_dtls_message(val),
1460 "end-of-candidates" => Ok(SdpAttribute::EndOfCandidates),
1461 "ice-lite" => Ok(SdpAttribute::IceLite),
1462 "ice-mismatch" => Ok(SdpAttribute::IceMismatch),
1463 "extmap-allow-mixed" => Ok(SdpAttribute::ExtmapAllowMixed),
1464 "ice-pwd" => Ok(SdpAttribute::IcePwd(string_or_empty(val)?)),
1465 "ice-ufrag" => Ok(SdpAttribute::IceUfrag(string_or_empty(val)?)),
1466 "identity" => Ok(SdpAttribute::Identity(string_or_empty(val)?)),
1467 "imageattr" => parse_image_attr(val),
1468 "inactive" => Ok(SdpAttribute::Inactive),
1469 "label" => Ok(SdpAttribute::Label(string_or_empty(val)?)),
1470 "max-message-size" => Ok(SdpAttribute::MaxMessageSize(val.parse()?)),
1471 "maxptime" => Ok(SdpAttribute::MaxPtime(val.parse()?)),
1472 "mid" => Ok(SdpAttribute::Mid(string_or_empty(val)?)),
1473 "msid-semantic" => parse_msid_semantic(val),
1474 "ptime" => Ok(SdpAttribute::Ptime(val.parse()?)),
1475 "ice-pacing" => parse_ice_pacing(val),
1476 "rid" => parse_rid(val),
1477 "recvonly" => Ok(SdpAttribute::Recvonly),
1478 "rtcp-mux" => Ok(SdpAttribute::RtcpMux),
1479 "rtcp-mux-only" => Ok(SdpAttribute::RtcpMuxOnly),
1480 "rtcp-rsize" => Ok(SdpAttribute::RtcpRsize),
1481 "sendonly" => Ok(SdpAttribute::Sendonly),
1482 "sendrecv" => Ok(SdpAttribute::Sendrecv),
1483 "ssrc-group" => parse_ssrc_group(val),
1484 "sctp-port" => parse_sctp_port(val),
1485 "candidate" => parse_candidate(val),
1486 "extmap" => parse_extmap(val),
1487 "fingerprint" => parse_fingerprint(val),
1488 "fmtp" => parse_fmtp(val),
1489 "framerate" => parse_framerate(val),
1490 "group" => parse_group(val),
1491 "ice-options" => parse_ice_options(val),
1492 "msid" => parse_msid(val),
1493 "remote-candidates" => parse_remote_candidates(val),
1494 "rtpmap" => parse_rtpmap(val),
1495 "rtcp" => parse_rtcp(val),
1496 "rtcp-fb" => parse_rtcp_fb(val),
1497 "sctpmap" => parse_sctpmap(val),
1498 "setup" => parse_setup(val),
1499 "simulcast" => parse_simulcast(val),
1500 "ssrc" => parse_ssrc(val),
1501 _ => Err(SdpParserInternalError::Unsupported(format!(
1502 "Unknown attribute type {name}",
1503 ))),
1504 }
1505 }
1506}
1507
1508impl fmt::Display for SdpAttribute {
1509 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1510 let attr_type_name = SdpAttributeType::from(self).to_string();
1511 let attr_to_string = |attr_str: String| attr_type_name + ":" + &attr_str;
1512 match *self {
1513 SdpAttribute::BundleOnly => SdpAttributeType::BundleOnly.to_string(),
1514 SdpAttribute::Candidate(ref a) => attr_to_string(a.to_string()),
1515 SdpAttribute::DtlsMessage(ref a) => attr_to_string(a.to_string()),
1516 SdpAttribute::EndOfCandidates => SdpAttributeType::EndOfCandidates.to_string(),
1517 SdpAttribute::Extmap(ref a) => attr_to_string(a.to_string()),
1518 SdpAttribute::ExtmapAllowMixed => SdpAttributeType::ExtmapAllowMixed.to_string(),
1519 SdpAttribute::Fingerprint(ref a) => attr_to_string(a.to_string()),
1520 SdpAttribute::Fmtp(ref a) => attr_to_string(a.to_string()),
1521 SdpAttribute::FrameRate(ref a) => attr_to_string(a.to_string()),
1522 SdpAttribute::Group(ref a) => attr_to_string(a.to_string()),
1523 SdpAttribute::IceLite => SdpAttributeType::IceLite.to_string(),
1524 SdpAttribute::IceMismatch => SdpAttributeType::IceMismatch.to_string(),
1525 SdpAttribute::IceOptions(ref a) => attr_to_string(a.join(" ")),
1526 SdpAttribute::IcePacing(ref a) => attr_to_string(a.to_string()),
1527 SdpAttribute::IcePwd(ref a) => attr_to_string(a.to_string()),
1528 SdpAttribute::IceUfrag(ref a) => attr_to_string(a.to_string()),
1529 SdpAttribute::Identity(ref a) => attr_to_string(a.to_string()),
1530 SdpAttribute::ImageAttr(ref a) => attr_to_string(a.to_string()),
1531 SdpAttribute::Inactive => SdpAttributeType::Inactive.to_string(),
1532 SdpAttribute::Label(ref a) => attr_to_string(a.to_string()),
1533 SdpAttribute::MaxMessageSize(ref a) => attr_to_string(a.to_string()),
1534 SdpAttribute::MaxPtime(ref a) => attr_to_string(a.to_string()),
1535 SdpAttribute::Mid(ref a) => attr_to_string(a.to_string()),
1536 SdpAttribute::Msid(ref a) => attr_to_string(a.to_string()),
1537 SdpAttribute::MsidSemantic(ref a) => attr_to_string(a.to_string()),
1538 SdpAttribute::Ptime(ref a) => attr_to_string(a.to_string()),
1539 SdpAttribute::Rid(ref a) => attr_to_string(a.to_string()),
1540 SdpAttribute::Recvonly => SdpAttributeType::Recvonly.to_string(),
1541 SdpAttribute::RemoteCandidate(ref a) => attr_to_string(a.to_string()),
1542 SdpAttribute::Rtpmap(ref a) => attr_to_string(a.to_string()),
1543 SdpAttribute::Rtcp(ref a) => attr_to_string(a.to_string()),
1544 SdpAttribute::Rtcpfb(ref a) => attr_to_string(a.to_string()),
1545 SdpAttribute::RtcpMux => SdpAttributeType::RtcpMux.to_string(),
1546 SdpAttribute::RtcpMuxOnly => SdpAttributeType::RtcpMuxOnly.to_string(),
1547 SdpAttribute::RtcpRsize => SdpAttributeType::RtcpRsize.to_string(),
1548 SdpAttribute::Sctpmap(ref a) => attr_to_string(a.to_string()),
1549 SdpAttribute::SctpPort(ref a) => attr_to_string(a.to_string()),
1550 SdpAttribute::Sendonly => SdpAttributeType::Sendonly.to_string(),
1551 SdpAttribute::Sendrecv => SdpAttributeType::Sendrecv.to_string(),
1552 SdpAttribute::Setup(ref a) => attr_to_string(a.to_string()),
1553 SdpAttribute::Simulcast(ref a) => attr_to_string(a.to_string()),
1554 SdpAttribute::Ssrc(ref a) => attr_to_string(a.to_string()),
1555 SdpAttribute::SsrcGroup(ref a, ref ssrcs) => {
1556 let stringified_ssrcs: Vec<String> =
1557 ssrcs.iter().map(|ssrc| ssrc.to_string()).collect();
1558 attr_to_string(a.to_string()) + " " + &stringified_ssrcs.join(" ")
1559 }
1560 }
1561 .fmt(f)
1562 }
1563}
1564
1565impl AnonymizingClone for SdpAttribute {
1566 fn masked_clone(&self, anon: &mut StatefulSdpAnonymizer) -> Self {
1567 match self {
1568 SdpAttribute::Candidate(i) => SdpAttribute::Candidate(i.masked_clone(anon)),
1569 SdpAttribute::Fingerprint(i) => SdpAttribute::Fingerprint(i.masked_clone(anon)),
1570 SdpAttribute::IcePwd(i) => SdpAttribute::IcePwd(anon.mask_ice_password(i)),
1571 SdpAttribute::IceUfrag(i) => SdpAttribute::IceUfrag(anon.mask_ice_user(i)),
1572 SdpAttribute::RemoteCandidate(i) => SdpAttribute::RemoteCandidate(i.masked_clone(anon)),
1573 SdpAttribute::Ssrc(i) => SdpAttribute::Ssrc(i.masked_clone(anon)),
1574 _ => self.clone(),
1575 }
1576 }
1577}
1578
1579#[derive(Clone, PartialEq)]
1580pub enum SdpAttributeType {
1581 BundleOnly,
1582 Candidate,
1583 DtlsMessage,
1584 EndOfCandidates,
1585 Extmap,
1586 ExtmapAllowMixed,
1587 Fingerprint,
1588 Fmtp,
1589 FrameRate,
1590 Group,
1591 IceLite,
1592 IceMismatch,
1593 IceOptions,
1594 IcePacing,
1595 IcePwd,
1596 IceUfrag,
1597 Identity,
1598 ImageAttr,
1599 Inactive,
1600 Label,
1601 MaxMessageSize,
1602 MaxPtime,
1603 Mid,
1604 Msid,
1605 MsidSemantic,
1606 Ptime,
1607 Rid,
1608 Recvonly,
1609 RemoteCandidate,
1610 Rtpmap,
1611 Rtcp,
1612 Rtcpfb,
1613 RtcpMux,
1614 RtcpMuxOnly,
1615 RtcpRsize,
1616 Sctpmap,
1617 SctpPort,
1618 Sendonly,
1619 Sendrecv,
1620 Setup,
1621 Simulcast,
1622 Ssrc,
1623 SsrcGroup,
1624}
1625
1626impl<'a> From<&'a SdpAttribute> for SdpAttributeType {
1627 fn from(other: &SdpAttribute) -> Self {
1628 match *other {
1629 SdpAttribute::BundleOnly { .. } => SdpAttributeType::BundleOnly,
1630 SdpAttribute::Candidate { .. } => SdpAttributeType::Candidate,
1631 SdpAttribute::DtlsMessage { .. } => SdpAttributeType::DtlsMessage,
1632 SdpAttribute::EndOfCandidates { .. } => SdpAttributeType::EndOfCandidates,
1633 SdpAttribute::Extmap { .. } => SdpAttributeType::Extmap,
1634 SdpAttribute::ExtmapAllowMixed { .. } => SdpAttributeType::ExtmapAllowMixed,
1635 SdpAttribute::Fingerprint { .. } => SdpAttributeType::Fingerprint,
1636 SdpAttribute::Fmtp { .. } => SdpAttributeType::Fmtp,
1637 SdpAttribute::FrameRate { .. } => SdpAttributeType::FrameRate,
1638 SdpAttribute::Group { .. } => SdpAttributeType::Group,
1639 SdpAttribute::IceLite { .. } => SdpAttributeType::IceLite,
1640 SdpAttribute::IceMismatch { .. } => SdpAttributeType::IceMismatch,
1641 SdpAttribute::IceOptions { .. } => SdpAttributeType::IceOptions,
1642 SdpAttribute::IcePacing { .. } => SdpAttributeType::IcePacing,
1643 SdpAttribute::IcePwd { .. } => SdpAttributeType::IcePwd,
1644 SdpAttribute::IceUfrag { .. } => SdpAttributeType::IceUfrag,
1645 SdpAttribute::Identity { .. } => SdpAttributeType::Identity,
1646 SdpAttribute::ImageAttr { .. } => SdpAttributeType::ImageAttr,
1647 SdpAttribute::Inactive { .. } => SdpAttributeType::Inactive,
1648 SdpAttribute::Label { .. } => SdpAttributeType::Label,
1649 SdpAttribute::MaxMessageSize { .. } => SdpAttributeType::MaxMessageSize,
1650 SdpAttribute::MaxPtime { .. } => SdpAttributeType::MaxPtime,
1651 SdpAttribute::Mid { .. } => SdpAttributeType::Mid,
1652 SdpAttribute::Msid { .. } => SdpAttributeType::Msid,
1653 SdpAttribute::MsidSemantic { .. } => SdpAttributeType::MsidSemantic,
1654 SdpAttribute::Ptime { .. } => SdpAttributeType::Ptime,
1655 SdpAttribute::Rid { .. } => SdpAttributeType::Rid,
1656 SdpAttribute::Recvonly { .. } => SdpAttributeType::Recvonly,
1657 SdpAttribute::RemoteCandidate { .. } => SdpAttributeType::RemoteCandidate,
1658 SdpAttribute::Rtcp { .. } => SdpAttributeType::Rtcp,
1659 SdpAttribute::Rtcpfb { .. } => SdpAttributeType::Rtcpfb,
1660 SdpAttribute::RtcpMux { .. } => SdpAttributeType::RtcpMux,
1661 SdpAttribute::RtcpMuxOnly { .. } => SdpAttributeType::RtcpMuxOnly,
1662 SdpAttribute::RtcpRsize { .. } => SdpAttributeType::RtcpRsize,
1663 SdpAttribute::Rtpmap { .. } => SdpAttributeType::Rtpmap,
1664 SdpAttribute::Sctpmap { .. } => SdpAttributeType::Sctpmap,
1665 SdpAttribute::SctpPort { .. } => SdpAttributeType::SctpPort,
1666 SdpAttribute::Sendonly { .. } => SdpAttributeType::Sendonly,
1667 SdpAttribute::Sendrecv { .. } => SdpAttributeType::Sendrecv,
1668 SdpAttribute::Setup { .. } => SdpAttributeType::Setup,
1669 SdpAttribute::Simulcast { .. } => SdpAttributeType::Simulcast,
1670 SdpAttribute::Ssrc { .. } => SdpAttributeType::Ssrc,
1671 SdpAttribute::SsrcGroup { .. } => SdpAttributeType::SsrcGroup,
1672 }
1673 }
1674}
1675
1676impl fmt::Display for SdpAttributeType {
1677 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1678 match *self {
1679 SdpAttributeType::BundleOnly => "bundle-only",
1680 SdpAttributeType::Candidate => "candidate",
1681 SdpAttributeType::DtlsMessage => "dtls-message",
1682 SdpAttributeType::EndOfCandidates => "end-of-candidates",
1683 SdpAttributeType::Extmap => "extmap",
1684 SdpAttributeType::ExtmapAllowMixed => "extmap-allow-mixed",
1685 SdpAttributeType::Fingerprint => "fingerprint",
1686 SdpAttributeType::Fmtp => "fmtp",
1687 SdpAttributeType::FrameRate => "framerate",
1688 SdpAttributeType::Group => "group",
1689 SdpAttributeType::IceLite => "ice-lite",
1690 SdpAttributeType::IceMismatch => "ice-mismatch",
1691 SdpAttributeType::IceOptions => "ice-options",
1692 SdpAttributeType::IcePacing => "ice-pacing",
1693 SdpAttributeType::IcePwd => "ice-pwd",
1694 SdpAttributeType::IceUfrag => "ice-ufrag",
1695 SdpAttributeType::Identity => "identity",
1696 SdpAttributeType::ImageAttr => "imageattr",
1697 SdpAttributeType::Inactive => "inactive",
1698 SdpAttributeType::Label => "label",
1699 SdpAttributeType::MaxMessageSize => "max-message-size",
1700 SdpAttributeType::MaxPtime => "maxptime",
1701 SdpAttributeType::Mid => "mid",
1702 SdpAttributeType::Msid => "msid",
1703 SdpAttributeType::MsidSemantic => "msid-semantic",
1704 SdpAttributeType::Ptime => "ptime",
1705 SdpAttributeType::Rid => "rid",
1706 SdpAttributeType::Recvonly => "recvonly",
1707 SdpAttributeType::RemoteCandidate => "remote-candidates",
1708 SdpAttributeType::Rtpmap => "rtpmap",
1709 SdpAttributeType::Rtcp => "rtcp",
1710 SdpAttributeType::Rtcpfb => "rtcp-fb",
1711 SdpAttributeType::RtcpMux => "rtcp-mux",
1712 SdpAttributeType::RtcpMuxOnly => "rtcp-mux-only",
1713 SdpAttributeType::RtcpRsize => "rtcp-rsize",
1714 SdpAttributeType::Sctpmap => "sctpmap",
1715 SdpAttributeType::SctpPort => "sctp-port",
1716 SdpAttributeType::Sendonly => "sendonly",
1717 SdpAttributeType::Sendrecv => "sendrecv",
1718 SdpAttributeType::Setup => "setup",
1719 SdpAttributeType::Simulcast => "simulcast",
1720 SdpAttributeType::Ssrc => "ssrc",
1721 SdpAttributeType::SsrcGroup => "ssrc-group",
1722 }
1723 .fmt(f)
1724 }
1725}
1726
1727fn string_or_empty(to_parse: &str) -> Result<String, SdpParserInternalError> {
1728 if to_parse.is_empty() {
1729 Err(SdpParserInternalError::Generic(
1730 "This attribute is required to have a value".to_string(),
1731 ))
1732 } else {
1733 Ok(to_parse.to_string())
1734 }
1735}
1736
1737fn parse_payload_type(to_parse: &str) -> Result<SdpAttributePayloadType, SdpParserInternalError> {
1738 Ok(match to_parse {
1739 "*" => SdpAttributePayloadType::Wildcard,
1740 _ => SdpAttributePayloadType::PayloadType(to_parse.parse::<u8>()?),
1741 })
1742}
1743
1744fn parse_single_direction(to_parse: &str) -> Result<SdpSingleDirection, SdpParserInternalError> {
1745 match to_parse {
1746 "send" => Ok(SdpSingleDirection::Send),
1747 "recv" => Ok(SdpSingleDirection::Recv),
1748 x => Err(SdpParserInternalError::Generic(format!(
1749 "Unknown direction description found: '{x:}'"
1750 ))),
1751 }
1752}
1753
1754fn parse_ssrc_group(to_parse: &str) -> Result<SdpAttribute, SdpParserInternalError> {
1759 let mut tokens = to_parse.split_whitespace();
1760 let semantics = match tokens.next() {
1761 None => {
1762 return Err(SdpParserInternalError::Generic(
1763 "Ssrc group attribute is missing semantics".to_string(),
1764 ));
1765 }
1766 Some(x) => match x.to_uppercase().as_ref() {
1767 "DUP" => SdpSsrcGroupSemantic::Duplication,
1768 "FID" => SdpSsrcGroupSemantic::FlowIdentification,
1769 "FEC" => SdpSsrcGroupSemantic::ForwardErrorCorrection,
1770 "FEC-FR" => SdpSsrcGroupSemantic::ForwardErrorCorrectionFr,
1771 "SIM" => SdpSsrcGroupSemantic::Sim,
1772 unknown => {
1773 return Err(SdpParserInternalError::Unsupported(format!(
1774 "Unknown ssrc semantic '{unknown:?}' found"
1775 )));
1776 }
1777 },
1778 };
1779
1780 let mut ssrcs = Vec::new();
1781 for token in tokens {
1782 match parse_ssrc(token) {
1783 Ok(SdpAttribute::Ssrc(ssrc)) => {
1784 ssrcs.push(ssrc);
1785 }
1786 Err(err) => {
1787 return Err(err);
1788 }
1789 _ => unreachable!(),
1790 }
1791 }
1792
1793 if ssrcs.is_empty() {
1794 return Err(SdpParserInternalError::Generic(
1795 "Ssrc group must contain at least one ssrc".to_string(),
1796 ));
1797 }
1798
1799 Ok(SdpAttribute::SsrcGroup(semantics, ssrcs))
1800}
1801
1802fn parse_sctp_port(to_parse: &str) -> Result<SdpAttribute, SdpParserInternalError> {
1807 let port = to_parse.parse()?;
1808 if port > 65535 {
1809 return Err(SdpParserInternalError::Generic(format!(
1810 "Sctpport port {port} can only be a bit 16bit number"
1811 )));
1812 }
1813 Ok(SdpAttribute::SctpPort(port))
1814}
1815
1816fn parse_candidate(to_parse: &str) -> Result<SdpAttribute, SdpParserInternalError> {
1843 let tokens: Vec<&str> = to_parse.split_whitespace().collect();
1844 if tokens.len() < 8 {
1845 return Err(SdpParserInternalError::Generic(
1846 "Candidate needs to have minimum eigth tokens".to_string(),
1847 ));
1848 }
1849 let component = tokens[1].parse::<u32>()?;
1850 let transport = match tokens[2].to_lowercase().as_ref() {
1851 "udp" => SdpAttributeCandidateTransport::Udp,
1852 "tcp" => SdpAttributeCandidateTransport::Tcp,
1853 _ => {
1854 return Err(SdpParserInternalError::Generic(
1855 "Unknonw candidate transport value".to_string(),
1856 ));
1857 }
1858 };
1859 let priority = tokens[3].parse::<u64>()?;
1860 let address = Address::from_str(tokens[4])?;
1861 let port = tokens[5].parse::<u32>()?;
1862 if port > 65535 {
1863 return Err(SdpParserInternalError::Generic(
1864 "ICE candidate port can only be a bit 16bit number".to_string(),
1865 ));
1866 }
1867 match tokens[6].to_lowercase().as_ref() {
1868 "typ" => (),
1869 _ => {
1870 return Err(SdpParserInternalError::Generic(
1871 "Candidate attribute token must be 'typ'".to_string(),
1872 ));
1873 }
1874 };
1875 let cand_type = match tokens[7].to_lowercase().as_ref() {
1876 "host" => SdpAttributeCandidateType::Host,
1877 "srflx" => SdpAttributeCandidateType::Srflx,
1878 "prflx" => SdpAttributeCandidateType::Prflx,
1879 "relay" => SdpAttributeCandidateType::Relay,
1880 _ => {
1881 return Err(SdpParserInternalError::Generic(
1882 "Unknow candidate type value".to_string(),
1883 ));
1884 }
1885 };
1886 let mut cand = SdpAttributeCandidate::new(
1887 tokens[0].to_string(),
1888 component,
1889 transport,
1890 priority,
1891 address,
1892 port,
1893 cand_type,
1894 );
1895 if tokens.len() > 8 {
1896 let mut index = 8;
1897 while tokens.len() > index + 1 {
1898 match tokens[index].to_lowercase().as_ref() {
1899 "generation" => {
1900 let generation = tokens[index + 1].parse::<u32>()?;
1901 cand.set_generation(generation);
1902 index += 2;
1903 }
1904 "network-cost" => {
1905 let cost = tokens[index + 1].parse::<u32>()?;
1906 cand.set_network_cost(cost);
1907 index += 2;
1908 }
1909 "raddr" => {
1910 let addr = parse_unicast_address(tokens[index + 1])?;
1911 cand.set_remote_address(addr);
1912 index += 2;
1913 }
1914 "rport" => {
1915 let port = tokens[index + 1].parse::<u32>()?;
1916 if port > 65535 {
1917 return Err(SdpParserInternalError::Generic(
1918 "ICE candidate rport can only be a bit 16bit number".to_string(),
1919 ));
1920 }
1921 cand.set_remote_port(port);
1922 index += 2;
1923 }
1924 "tcptype" => {
1925 cand.set_tcp_type(match tokens[index + 1].to_lowercase().as_ref() {
1926 "active" => SdpAttributeCandidateTcpType::Active,
1927 "passive" => SdpAttributeCandidateTcpType::Passive,
1928 "so" => SdpAttributeCandidateTcpType::Simultaneous,
1929 _ => {
1930 return Err(SdpParserInternalError::Generic(
1931 "Unknown tcptype value in candidate line".to_string(),
1932 ));
1933 }
1934 });
1935 index += 2;
1936 }
1937 "ufrag" => {
1938 let ufrag = tokens[index + 1];
1939 cand.set_ufrag(ufrag.to_string());
1940 index += 2;
1941 }
1942 _ => {
1943 let name = tokens[index].to_string();
1944 let value = tokens[index + 1].to_string();
1945 cand.add_unknown_extension(name, value);
1946 index += 2;
1947 }
1948 };
1949 }
1950 if tokens.len() > index {
1951 return Err(SdpParserInternalError::Unsupported(
1952 "Ice candidate extension name without value".to_string(),
1953 ));
1954 }
1955 }
1956 Ok(SdpAttribute::Candidate(cand))
1957}
1958
1959fn parse_dtls_message(to_parse: &str) -> Result<SdpAttribute, SdpParserInternalError> {
1971 let tokens: Vec<&str> = to_parse.split(' ').collect();
1972
1973 if tokens.len() != 2 {
1974 return Err(SdpParserInternalError::Generic(
1975 "dtls-message must have a role token and a value token.".to_string(),
1976 ));
1977 }
1978
1979 Ok(SdpAttribute::DtlsMessage(match tokens[0] {
1980 "client" => SdpAttributeDtlsMessage::Client(tokens[1].to_string()),
1981 "server" => SdpAttributeDtlsMessage::Server(tokens[1].to_string()),
1982 e => {
1983 return Err(SdpParserInternalError::Generic(format!(
1984 "dtls-message has unknown role token '{e}'"
1985 )));
1986 }
1987 }))
1988}
1989
1990fn valid_byte_string(input: &str) -> bool {
1993 !(input.contains(0x00 as char) || input.contains(0x0A as char) || input.contains(0x0D as char))
1994}
1995
1996fn parse_extmap(to_parse: &str) -> Result<SdpAttribute, SdpParserInternalError> {
2018 let tokens: Vec<&str> = to_parse.split_whitespace().collect();
2019 if tokens.len() < 2 {
2020 return Err(SdpParserInternalError::Generic(
2021 "Extmap needs to have at least two tokens".to_string(),
2022 ));
2023 }
2024 let id: u16;
2025 let mut direction: Option<SdpAttributeDirection> = None;
2026 if tokens[0].find('/').is_none() {
2027 id = tokens[0].parse::<u16>()?;
2028 } else {
2029 let id_dir: Vec<&str> = tokens[0].splitn(2, '/').collect();
2030 id = id_dir[0].parse::<u16>()?;
2031 direction = Some(match id_dir[1].to_lowercase().as_ref() {
2032 "recvonly" => SdpAttributeDirection::Recvonly,
2033 "sendonly" => SdpAttributeDirection::Sendonly,
2034 "sendrecv" => SdpAttributeDirection::Sendrecv,
2035 _ => {
2036 return Err(SdpParserInternalError::Generic(
2037 "Unsupported direction in extmap value".to_string(),
2038 ));
2039 }
2040 })
2041 }
2042 let extension_attributes = if tokens.len() == 2 {
2044 None
2045 } else {
2046 let ext_string: String = tokens[2..].join(" ");
2047 if !valid_byte_string(&ext_string) {
2048 return Err(SdpParserInternalError::Generic(
2049 "Illegal character in extmap extension attributes".to_string(),
2050 ));
2051 }
2052 Some(ext_string)
2053 };
2054 Ok(SdpAttribute::Extmap(SdpAttributeExtmap {
2055 id,
2056 direction,
2057 url: tokens[1].to_string(),
2058 extension_attributes,
2059 }))
2060}
2061
2062fn parse_fingerprint(to_parse: &str) -> Result<SdpAttribute, SdpParserInternalError> {
2079 let tokens: Vec<&str> = to_parse.split_whitespace().collect();
2080 if tokens.len() != 2 {
2081 return Err(SdpParserInternalError::Generic(
2082 "Fingerprint needs to have two tokens".to_string(),
2083 ));
2084 }
2085
2086 let hash_algorithm = SdpAttributeFingerprintHashType::try_from_name(tokens[0])?;
2087 let bytes = hash_algorithm.parse_octets(tokens[1])?;
2088 let fingerprint = SdpAttributeFingerprint::try_from((hash_algorithm, bytes))?;
2089 Ok(SdpAttribute::Fingerprint(fingerprint))
2090}
2091
2092fn parse_fmtp(to_parse: &str) -> Result<SdpAttribute, SdpParserInternalError> {
2097 let tokens: Vec<&str> = to_parse.splitn(2, ' ').collect();
2098
2099 if tokens.len() != 2 {
2101 return Err(SdpParserInternalError::Unsupported(
2102 "Fmtp attributes require a payload type and a parameter block.".to_string(),
2103 ));
2104 }
2105
2106 let payload_token = tokens[0];
2107
2108 let mut parameters = SdpAttributeFmtpParameters {
2110 packetization_mode: 0,
2111 level_asymmetry_allowed: false,
2112 profile_level_id: 0x0042_0010,
2113 max_fs: 0,
2114 max_cpb: 0,
2115 max_dpb: 0,
2116 max_br: 0,
2117 max_mbps: 0,
2118 usedtx: false,
2119 stereo: false,
2120 useinbandfec: false,
2121 cbr: false,
2122 max_fr: 0,
2123 profile: None,
2124 level_idx: None,
2125 tier: None,
2126 maxplaybackrate: 48000,
2127 maxaveragebitrate: 0,
2128 ptime: 0,
2129 minptime: 0,
2130 maxptime: 0,
2131 encodings: Vec::new(),
2132 dtmf_tones: "".to_string(),
2133 rtx: None,
2134 unknown_tokens: Vec::new(),
2135 };
2136
2137 for parameter_token in tokens[1..].iter() {
2138 if parameter_token.contains('=') {
2139 let parameter_tokens: Vec<&str> = parameter_token
2141 .split(';')
2142 .filter(|token| !token.is_empty())
2143 .collect();
2144 for parameter_token in parameter_tokens.iter() {
2145 let name_value_pair: Vec<&str> = parameter_token.splitn(2, '=').collect();
2146 if name_value_pair.len() != 2 {
2147 return Err(SdpParserInternalError::Generic(
2148 "A fmtp parameter must be either a telephone event, a parameter list or a red codec list"
2149 .to_string(),
2150 ));
2151 }
2152
2153 let parse_bool =
2154 |val: &str, param_name: &str| -> Result<bool, SdpParserInternalError> {
2155 match val.parse::<u8>()? {
2156 0 => Ok(false),
2157 1 => Ok(true),
2158 _ => Err(SdpParserInternalError::Generic(format!(
2159 "The fmtp parameter '{param_name:}' must be 0 or 1"
2160 ))),
2161 }
2162 };
2163
2164 let parameter_name = name_value_pair[0];
2165 let parameter_val = name_value_pair[1];
2166
2167 match parameter_name.to_uppercase().as_str() {
2168 "PROFILE-LEVEL-ID" => parameters.profile_level_id = match u32::from_str_radix(
2170 parameter_val,
2171 16,
2172 )? {
2173 x @ 0..=0x00ff_ffff => x,
2174 _ => return Err(SdpParserInternalError::Generic(
2175 "The fmtp parameter 'profile-level-id' must be in range [0,0xffffff]"
2176 .to_string(),
2177 )),
2178 },
2179 "PACKETIZATION-MODE" => {
2180 parameters.packetization_mode = match parameter_val.parse::<u32>()? {
2181 x @ 0..=2 => x,
2182 _ => {
2183 return Err(SdpParserInternalError::Generic(
2184 "The fmtp parameter 'packetization-mode' must be 0,1 or 2"
2185 .to_string(),
2186 ));
2187 }
2188 }
2189 }
2190 "LEVEL-ASYMMETRY-ALLOWED" => {
2191 parameters.level_asymmetry_allowed =
2192 parse_bool(parameter_val, "level-asymmetry-allowed")?
2193 }
2194 "MAX-MBPS" => parameters.max_mbps = parameter_val.parse::<u32>()?,
2195 "MAX-FS" => parameters.max_fs = parameter_val.parse::<u32>()?,
2196 "MAX-CPB" => parameters.max_cpb = parameter_val.parse::<u32>()?,
2197 "MAX-DPB" => parameters.max_dpb = parameter_val.parse::<u32>()?,
2198 "MAX-BR" => parameters.max_br = parameter_val.parse::<u32>()?,
2199
2200 "MAX-FR" => parameters.max_fr = parameter_val.parse::<u32>()?,
2202
2203 "PROFILE" => {
2205 parameters.profile = match parameter_val.parse::<u8>()? {
2206 x @ 0..=2 => Some(x),
2207 _ => {
2208 return Err(SdpParserInternalError::Generic(
2209 "The fmtp parameter 'profile' must be in the range [0,2]"
2210 .to_string(),
2211 ));
2212 }
2213 }
2214 }
2215 "LEVEL-IDX" => {
2216 parameters.level_idx = match parameter_val.parse::<u8>()? {
2217 x @ 0..=31 => Some(x),
2218 _ => {
2219 return Err(SdpParserInternalError::Generic(
2220 "The fmtp parameter 'level-idx' must be in the range [0,31]"
2221 .to_string(),
2222 ));
2223 }
2224 }
2225 }
2226 "TIER" => {
2227 parameters.tier = match parameter_val.parse::<u8>()? {
2228 x @ 0..=1 => Some(x),
2229 _ => {
2230 return Err(SdpParserInternalError::Generic(
2231 "The fmtp parameter 'tier' must be in the range [0,1]"
2232 .to_string(),
2233 ));
2234 }
2235 }
2236 }
2237 "MAXPLAYBACKRATE" => {
2239 parameters.maxplaybackrate = parameter_val.parse::<u32>()?
2240 }
2241 "MAXAVERAGEBITRATE" => {
2242 parameters.maxaveragebitrate = parameter_val.parse::<u32>()?
2243 }
2244 "PTIME" => parameters.ptime = parameter_val.parse::<u32>()?,
2245 "MAXPTIME" => parameters.maxptime = parameter_val.parse::<u32>()?,
2246 "MINPTIME" => parameters.minptime = parameter_val.parse::<u32>()?,
2247 "USEDTX" => parameters.usedtx = parse_bool(parameter_val, "usedtx")?,
2248 "STEREO" => parameters.stereo = parse_bool(parameter_val, "stereo")?,
2249 "USEINBANDFEC" => {
2250 parameters.useinbandfec = parse_bool(parameter_val, "useinbandfec")?
2251 }
2252 "CBR" => parameters.cbr = parse_bool(parameter_val, "cbr")?,
2253 "APT" => {
2254 parameters.rtx = Some(RtxFmtpParameters {
2255 apt: parameter_val.parse::<u8>()?,
2256 rtx_time: None,
2257 })
2258 }
2259 "RTX-TIME" => {
2260 if let Some(ref mut rtx) = parameters.rtx {
2261 rtx.rtx_time = Some(parameter_val.parse::<u32>()?)
2262 } else {
2263 return Err(SdpParserInternalError::Generic(
2264 "RTX codec must have an APT field".to_string(),
2265 ));
2266 }
2267 }
2268 _ => parameters
2269 .unknown_tokens
2270 .push((*parameter_token).to_string()),
2271 }
2272 }
2273 } else if parameter_token.contains('/') {
2274 let encodings: Vec<&str> = parameter_token.split('/').collect();
2275
2276 for encoding in encodings {
2277 match encoding.parse::<u8>()? {
2278 x @ 0..=128 => parameters.encodings.push(x),
2279 _ => {
2280 return Err(SdpParserInternalError::Generic(
2281 "Red codec must be in range [0,128]".to_string(),
2282 ));
2283 }
2284 }
2285 }
2286 } else {
2287 let dtmf_tones: Vec<&str> = parameter_token.split(',').collect();
2289 let mut dtmf_tone_is_ok = true;
2290
2291 let validate_digits = |digit_option: Option<u8>| -> Option<u8> {
2293 match digit_option {
2294 Some(x) => match x {
2295 0..=100 => Some(x),
2296 _ => None,
2297 },
2298 None => None,
2299 }
2300 };
2301
2302 for dtmf_tone in dtmf_tones {
2304 let dtmf_tone_range: Vec<&str> = dtmf_tone.splitn(2, '-').collect();
2305
2306 dtmf_tone_is_ok = match dtmf_tone_range.len() {
2307 2 => {
2309 match validate_digits(dtmf_tone_range[0].parse::<u8>().ok()) {
2310 Some(l) => match validate_digits(dtmf_tone_range[1].parse::<u8>().ok())
2311 {
2312 Some(u) => {
2313 l < u
2315 }
2316 None => false,
2317 },
2318 None => false,
2319 }
2320 }
2321 1 => validate_digits(dtmf_tone.parse::<u8>().ok()).is_some(),
2323 _ => false,
2324 };
2325
2326 if !dtmf_tone_is_ok {
2327 break;
2328 }
2329 }
2330
2331 parameters.dtmf_tones = if dtmf_tone_is_ok {
2333 (*parameter_token).to_string()
2334 } else {
2335 "0-15".to_string()
2336 };
2337 }
2338 }
2339 Ok(SdpAttribute::Fmtp(SdpAttributeFmtp {
2340 payload_type: payload_token.parse::<u8>()?,
2341 parameters,
2342 }))
2343}
2344
2345fn parse_framerate(to_parse: &str) -> Result<SdpAttribute, SdpParserInternalError> {
2350 let framerate: f64 = to_parse.parse()?;
2351
2352 if framerate.is_nan() {
2353 return Err(SdpParserInternalError::Generic(
2354 "FrameRate attribute must be a number".to_string(),
2355 ));
2356 }
2357
2358 if framerate.is_infinite() {
2359 return Err(SdpParserInternalError::Generic(
2360 "FrameRate attribute cannot be finite".to_string(),
2361 ));
2362 }
2363
2364 if framerate == 0.0 {
2365 return Err(SdpParserInternalError::Generic(
2366 "FrameRate attribute cannot be zero".to_string(),
2367 ));
2368 }
2369
2370 Ok(SdpAttribute::FrameRate(framerate))
2371}
2372
2373fn parse_group(to_parse: &str) -> Result<SdpAttribute, SdpParserInternalError> {
2382 let mut tokens = to_parse.split_whitespace();
2383 let semantics = match tokens.next() {
2384 None => {
2385 return Err(SdpParserInternalError::Generic(
2386 "Group attribute is missing semantics token".to_string(),
2387 ));
2388 }
2389 Some(x) => match x.to_uppercase().as_ref() {
2390 "LS" => SdpAttributeGroupSemantic::LipSynchronization,
2391 "FID" => SdpAttributeGroupSemantic::FlowIdentification,
2392 "SRF" => SdpAttributeGroupSemantic::SingleReservationFlow,
2393 "ANAT" => SdpAttributeGroupSemantic::AlternateNetworkAddressType,
2394 "FEC" => SdpAttributeGroupSemantic::ForwardErrorCorrection,
2395 "DDP" => SdpAttributeGroupSemantic::DecodingDependency,
2396 "BUNDLE" => SdpAttributeGroupSemantic::Bundle,
2397 unknown => {
2398 return Err(SdpParserInternalError::Unsupported(format!(
2399 "Unknown group semantic '{unknown:?}' found",
2400 )));
2401 }
2402 },
2403 };
2404 Ok(SdpAttribute::Group(SdpAttributeGroup {
2405 semantics,
2406 tags: tokens.map(ToString::to_string).collect(),
2407 }))
2408}
2409
2410fn parse_ice_options(to_parse: &str) -> Result<SdpAttribute, SdpParserInternalError> {
2417 if to_parse.is_empty() {
2418 return Err(SdpParserInternalError::Generic(
2419 "ice-options is required to have a value".to_string(),
2420 ));
2421 }
2422 Ok(SdpAttribute::IceOptions(
2423 to_parse
2424 .split_whitespace()
2425 .map(ToString::to_string)
2426 .collect(),
2427 ))
2428}
2429
2430fn parse_ice_pacing(to_parse: &str) -> Result<SdpAttribute, SdpParserInternalError> {
2436 let parsed = to_parse.parse::<u64>()?;
2437 if parsed >= 1_00_00_00_00_00 {
2438 return Err(SdpParserInternalError::Generic(
2439 "ice-pacing value is not a 10 digit integer".to_string(),
2440 ));
2441 }
2442 Ok(SdpAttribute::IcePacing(parsed))
2443}
2444
2445fn parse_imageattr_tokens(to_parse: &str, separator: char) -> Vec<String> {
2446 let mut tokens = Vec::new();
2447 let mut open_braces_counter = 0;
2448 let mut current_tokens = Vec::new();
2449
2450 for token in to_parse.split(separator) {
2451 if token.contains('[') {
2452 open_braces_counter += 1;
2453 }
2454 if token.contains(']') {
2455 open_braces_counter -= 1;
2456 }
2457
2458 current_tokens.push(token.to_string());
2459
2460 if open_braces_counter == 0 {
2461 tokens.push(current_tokens.join(&separator.to_string()));
2462 current_tokens = Vec::new();
2463 }
2464 }
2465
2466 tokens
2467}
2468
2469fn parse_imagettr_braced_token(to_parse: &str) -> Option<&str> {
2470 if !to_parse.starts_with('[') {
2471 return None;
2472 }
2473
2474 if !to_parse.ends_with(']') {
2475 return None;
2476 }
2477
2478 Some(&to_parse[1..to_parse.len() - 1])
2479}
2480
2481fn parse_image_attr_xyrange(
2482 to_parse: &str,
2483) -> Result<SdpAttributeImageAttrXyRange, SdpParserInternalError> {
2484 if to_parse.starts_with('[') {
2485 let value_tokens = parse_imagettr_braced_token(to_parse).ok_or_else(|| {
2486 SdpParserInternalError::Generic(
2487 "imageattr's xyrange has no closing tag ']'".to_string(),
2488 )
2489 })?;
2490
2491 if to_parse.contains(':') {
2492 let range_tokens: Vec<&str> = value_tokens.split(':').collect();
2494
2495 if range_tokens.len() == 3 {
2496 Ok(SdpAttributeImageAttrXyRange::Range(
2497 range_tokens[0].parse::<u32>()?,
2498 range_tokens[2].parse::<u32>()?,
2499 Some(range_tokens[1].parse::<u32>()?),
2500 ))
2501 } else if range_tokens.len() == 2 {
2502 Ok(SdpAttributeImageAttrXyRange::Range(
2503 range_tokens[0].parse::<u32>()?,
2504 range_tokens[1].parse::<u32>()?,
2505 None,
2506 ))
2507 } else {
2508 Err(SdpParserInternalError::Generic(
2509 "imageattr's xyrange must contain 2 or 3 fields".to_string(),
2510 ))
2511 }
2512 } else {
2513 let values = value_tokens
2515 .split(',')
2516 .map(str::parse::<u32>)
2517 .collect::<Result<Vec<u32>, _>>()?;
2518
2519 if values.len() < 2 {
2520 return Err(SdpParserInternalError::Generic(
2521 "imageattr's discrete value list must have at least two elements".to_string(),
2522 ));
2523 }
2524
2525 Ok(SdpAttributeImageAttrXyRange::DiscreteValues(values))
2526 }
2527 } else {
2528 Ok(SdpAttributeImageAttrXyRange::DiscreteValues(vec![
2529 to_parse.parse::<u32>()?
2530 ]))
2531 }
2532}
2533
2534fn parse_image_attr_set(
2535 to_parse: &str,
2536) -> Result<SdpAttributeImageAttrSet, SdpParserInternalError> {
2537 let mut tokens = parse_imageattr_tokens(to_parse, ',').into_iter();
2538
2539 let x_token = tokens.next().ok_or_else(|| {
2540 SdpParserInternalError::Generic("imageattr set is missing the 'x=' token".to_string())
2541 })?;
2542 if !x_token.starts_with("x=") {
2543 return Err(SdpParserInternalError::Generic(
2544 "The first token in an imageattr set must begin with 'x='".to_string(),
2545 ));
2546 }
2547 let x = parse_image_attr_xyrange(&x_token[2..])?;
2548
2549 let y_token = tokens.next().ok_or_else(|| {
2550 SdpParserInternalError::Generic("imageattr set is missing the 'y=' token".to_string())
2551 })?;
2552 if !y_token.starts_with("y=") {
2553 return Err(SdpParserInternalError::Generic(
2554 "The second token in an imageattr set must begin with 'y='".to_string(),
2555 ));
2556 }
2557 let y = parse_image_attr_xyrange(&y_token[2..])?;
2558
2559 let mut sar = None;
2560 let mut par = None;
2561 let mut q = None;
2562
2563 let parse_ps_range = |resolution_range: &str| -> Result<(f32, f32), SdpParserInternalError> {
2564 let minmax_pair: Vec<&str> = resolution_range.split('-').collect();
2565
2566 if minmax_pair.len() != 2 {
2567 return Err(SdpParserInternalError::Generic(
2568 "imageattr's par and sar ranges must have two components".to_string(),
2569 ));
2570 }
2571
2572 let min = minmax_pair[0].parse::<f32>()?;
2573 let max = minmax_pair[1].parse::<f32>()?;
2574
2575 if min >= max {
2576 return Err(SdpParserInternalError::Generic(
2577 "In imageattr's par and sar ranges, first must be < than the second".to_string(),
2578 ));
2579 }
2580
2581 Ok((min, max))
2582 };
2583
2584 for current_token in tokens {
2585 if let Some(value_token) = current_token.strip_prefix("sar=") {
2586 if value_token.starts_with('[') {
2587 let sar_values = parse_imagettr_braced_token(value_token).ok_or_else(|| {
2588 SdpParserInternalError::Generic(
2589 "imageattr's sar value is missing closing tag ']'".to_string(),
2590 )
2591 })?;
2592
2593 if value_token.contains('-') {
2594 let range = parse_ps_range(sar_values)?;
2596 sar = Some(SdpAttributeImageAttrSRange::Range(range.0, range.1))
2597 } else if value_token.contains(',') {
2598 let values = sar_values
2600 .split(',')
2601 .map(str::parse::<f32>)
2602 .collect::<Result<Vec<f32>, _>>()?;
2603
2604 if values.len() < 2 {
2605 return Err(SdpParserInternalError::Generic(
2606 "imageattr's sar discrete value list must have at least two values"
2607 .to_string(),
2608 ));
2609 }
2610
2611 let mut last_value = 0.0;
2613 for value in &values {
2614 if last_value >= *value {
2615 return Err(SdpParserInternalError::Generic(
2616 "imageattr's sar discrete value list must contain ascending values"
2617 .to_string(),
2618 ));
2619 }
2620 last_value = *value;
2621 }
2622 sar = Some(SdpAttributeImageAttrSRange::DiscreteValues(values))
2623 }
2624 } else {
2625 sar = Some(SdpAttributeImageAttrSRange::DiscreteValues(vec![
2626 value_token.parse::<f32>()?,
2627 ]))
2628 }
2629 } else if let Some(braced_value_token) = current_token.strip_prefix("par=") {
2630 if !braced_value_token.starts_with('[') {
2631 return Err(SdpParserInternalError::Generic(
2632 "imageattr's par value must start with '['".to_string(),
2633 ));
2634 }
2635
2636 let par_values = parse_imagettr_braced_token(braced_value_token).ok_or_else(|| {
2637 SdpParserInternalError::Generic(
2638 "imageattr's par value must be enclosed with ']'".to_string(),
2639 )
2640 })?;
2641 let range = parse_ps_range(par_values)?;
2642 par = Some(SdpAttributeImageAttrPRange {
2643 min: range.0,
2644 max: range.1,
2645 })
2646 } else if let Some(qval) = current_token.strip_prefix("q=") {
2647 q = Some(qval.parse::<f32>()?);
2648 }
2649 }
2650
2651 Ok(SdpAttributeImageAttrSet { x, y, sar, par, q })
2652}
2653
2654fn parse_image_attr_set_list<I>(
2655 tokens: &mut iter::Peekable<I>,
2656) -> Result<SdpAttributeImageAttrSetList, SdpParserInternalError>
2657where
2658 I: Iterator<Item = String> + Clone,
2659{
2660 let parse_set = |set_token: &str| -> Result<SdpAttributeImageAttrSet, SdpParserInternalError> {
2661 parse_image_attr_set(parse_imagettr_braced_token(set_token).ok_or_else(|| {
2662 SdpParserInternalError::Generic("imageattr sets must be enclosed by ']'".to_string())
2663 })?)
2664 };
2665
2666 match tokens
2667 .next()
2668 .ok_or_else(|| {
2669 SdpParserInternalError::Generic(
2670 "imageattr must have a parameter set after a direction token".to_string(),
2671 )
2672 })?
2673 .as_str()
2674 {
2675 "*" => Ok(SdpAttributeImageAttrSetList::Wildcard),
2676 x => {
2677 let mut sets = vec![parse_set(x)?];
2678 while let Some(set_str) = tokens.clone().peek() {
2679 if set_str.starts_with('[') {
2680 sets.push(parse_set(&tokens.next().unwrap())?);
2681 } else {
2682 break;
2683 }
2684 }
2685
2686 Ok(SdpAttributeImageAttrSetList::Sets(sets))
2687 }
2688 }
2689}
2690
2691fn parse_image_attr(to_parse: &str) -> Result<SdpAttribute, SdpParserInternalError> {
2760 let mut tokens = parse_imageattr_tokens(to_parse, ' ').into_iter().peekable();
2761
2762 let pt = parse_payload_type(
2763 tokens
2764 .next()
2765 .ok_or_else(|| {
2766 SdpParserInternalError::Generic("imageattr requires a payload token".to_string())
2767 })?
2768 .as_str(),
2769 )?;
2770 let first_direction = parse_single_direction(
2771 tokens
2772 .next()
2773 .ok_or_else(|| {
2774 SdpParserInternalError::Generic(
2775 "imageattr's second token must be a direction token".to_string(),
2776 )
2777 })?
2778 .as_str(),
2779 )?;
2780
2781 let first_set_list = parse_image_attr_set_list(&mut tokens)?;
2782
2783 let mut second_set_list = SdpAttributeImageAttrSetList::Sets(Vec::new());
2784
2785 if let Some(direction_token) = tokens.next() {
2787 if parse_single_direction(direction_token.as_str())? == first_direction {
2788 return Err(SdpParserInternalError::Generic(
2789 "imageattr's second direction token must be different from the first one"
2790 .to_string(),
2791 ));
2792 }
2793
2794 second_set_list = parse_image_attr_set_list(&mut tokens)?;
2795 }
2796
2797 if tokens.next().is_some() {
2798 return Err(SdpParserInternalError::Generic(
2799 "imageattr must not contain any token after the second set list".to_string(),
2800 ));
2801 }
2802
2803 Ok(SdpAttribute::ImageAttr(match first_direction {
2804 SdpSingleDirection::Send => SdpAttributeImageAttr {
2805 pt,
2806 send: first_set_list,
2807 recv: second_set_list,
2808 },
2809 SdpSingleDirection::Recv => SdpAttributeImageAttr {
2810 pt,
2811 send: second_set_list,
2812 recv: first_set_list,
2813 },
2814 }))
2815}
2816
2817fn parse_msid(to_parse: &str) -> Result<SdpAttribute, SdpParserInternalError> {
2824 let mut tokens = to_parse.split_whitespace();
2825 let id = match tokens.next() {
2826 None => {
2827 return Err(SdpParserInternalError::Generic(
2828 "Msid attribute is missing msid-id token".to_string(),
2829 ));
2830 }
2831 Some(x) => x.to_string(),
2832 };
2833 let appdata = tokens.next().map(|x| x.to_string());
2834 Ok(SdpAttribute::Msid(SdpAttributeMsid { id, appdata }))
2835}
2836
2837fn parse_msid_semantic(to_parse: &str) -> Result<SdpAttribute, SdpParserInternalError> {
2844 let tokens: Vec<_> = to_parse.split_whitespace().collect();
2845 if tokens.is_empty() {
2846 return Err(SdpParserInternalError::Generic(
2847 "Msid-semantic attribute is missing msid-semantic token".to_string(),
2848 ));
2849 }
2850 let semantic = SdpAttributeMsidSemantic {
2852 semantic: tokens[0].to_string(),
2853 msids: tokens[1..].iter().map(ToString::to_string).collect(),
2854 };
2855 Ok(SdpAttribute::MsidSemantic(semantic))
2856}
2857
2858fn parse_rid(to_parse: &str) -> Result<SdpAttribute, SdpParserInternalError> {
2894 let tokens: Vec<&str> = to_parse.splitn(3, ' ').collect();
2895
2896 if tokens.len() < 2 {
2897 return Err(SdpParserInternalError::Generic(
2898 "A rid attribute must at least have an id and a direction token.".to_string(),
2899 ));
2900 }
2901
2902 let mut params = SdpAttributeRidParameters {
2904 max_width: 0,
2905 max_height: 0,
2906 max_fps: 0,
2907 max_fs: 0,
2908 max_br: 0,
2909 max_pps: 0,
2910 unknown: Vec::new(),
2911 };
2912 let mut formats: Vec<u16> = Vec::new();
2913 let mut depends: Vec<String> = Vec::new();
2914
2915 if let Some(param_token) = tokens.get(2) {
2916 let mut parameters = param_token.split(';').peekable();
2917
2918 if let Some(maybe_fmt_parameter) = parameters.clone().peek() {
2921 if let Some(fmt_list) = maybe_fmt_parameter.strip_prefix("pt=") {
2922 for fmt in fmt_list.split(',') {
2923 formats.push(fmt.trim().parse::<u16>()?);
2924 }
2925 parameters.next();
2926 }
2927 }
2928
2929 for param in parameters {
2930 let param_value_pair: Vec<&str> = param.splitn(2, '=').collect();
2932 if param_value_pair.len() != 2 {
2933 return Err(SdpParserInternalError::Generic(
2934 "A rid parameter needs to be of form 'param=value'".to_string(),
2935 ));
2936 }
2937
2938 match param_value_pair[0] {
2939 "max-width" => params.max_width = param_value_pair[1].parse::<u32>()?,
2940 "max-height" => params.max_height = param_value_pair[1].parse::<u32>()?,
2941 "max-fps" => params.max_fps = param_value_pair[1].parse::<u32>()?,
2942 "max-fs" => params.max_fs = param_value_pair[1].parse::<u32>()?,
2943 "max-br" => params.max_br = param_value_pair[1].parse::<u32>()?,
2944 "max-pps" => params.max_pps = param_value_pair[1].parse::<u32>()?,
2945 "depends" => {
2946 depends.extend(param_value_pair[1].split(',').map(ToString::to_string));
2947 }
2948 _ => params.unknown.push(param.to_string()),
2949 }
2950 }
2951 }
2952
2953 Ok(SdpAttribute::Rid(SdpAttributeRid {
2954 id: tokens[0].to_string(),
2955 direction: parse_single_direction(tokens[1])?,
2956 formats,
2957 params,
2958 depends,
2959 }))
2960}
2961
2962fn parse_remote_candidates(to_parse: &str) -> Result<SdpAttribute, SdpParserInternalError> {
2969 let mut tokens = to_parse.split_whitespace();
2970 let component = match tokens.next() {
2971 None => {
2972 return Err(SdpParserInternalError::Generic(
2973 "Remote-candidate attribute is missing component ID".to_string(),
2974 ));
2975 }
2976 Some(x) => x.parse::<u32>()?,
2977 };
2978 let address = match tokens.next() {
2979 None => {
2980 return Err(SdpParserInternalError::Generic(
2981 "Remote-candidate attribute is missing connection address".to_string(),
2982 ));
2983 }
2984 Some(x) => parse_unicast_address(x)?,
2985 };
2986 let port = match tokens.next() {
2987 None => {
2988 return Err(SdpParserInternalError::Generic(
2989 "Remote-candidate attribute is missing port number".to_string(),
2990 ));
2991 }
2992 Some(x) => x.parse::<u32>()?,
2993 };
2994 if port > 65535 {
2995 return Err(SdpParserInternalError::Generic(
2996 "Remote-candidate port can only be a bit 16bit number".to_string(),
2997 ));
2998 };
2999 Ok(SdpAttribute::RemoteCandidate(SdpAttributeRemoteCandidate {
3000 component,
3001 address,
3002 port,
3003 }))
3004}
3005
3006fn parse_rtpmap(to_parse: &str) -> Result<SdpAttribute, SdpParserInternalError> {
3011 let mut tokens = to_parse.split_whitespace();
3012 let payload_type: u8 = match tokens.next() {
3013 None => {
3014 return Err(SdpParserInternalError::Generic(
3015 "Rtpmap missing payload type".to_string(),
3016 ));
3017 }
3018 Some(x) => {
3019 let pt = x.parse::<u8>()?;
3020 if pt > 127 {
3021 return Err(SdpParserInternalError::Generic(
3022 "Rtpmap payload type must be less then 127".to_string(),
3023 ));
3024 };
3025 pt
3026 }
3027 };
3028 let mut parameters = match tokens.next() {
3029 None => {
3030 return Err(SdpParserInternalError::Generic(
3031 "Rtpmap missing payload type".to_string(),
3032 ));
3033 }
3034 Some(x) => x.split('/'),
3035 };
3036 let name = match parameters.next() {
3037 None => {
3038 return Err(SdpParserInternalError::Generic(
3039 "Rtpmap missing codec name".to_string(),
3040 ));
3041 }
3042 Some(x) => x.to_string(),
3043 };
3044 let frequency = match parameters.next() {
3045 None => {
3046 return Err(SdpParserInternalError::Generic(
3047 "Rtpmap missing codec name".to_string(),
3048 ));
3049 }
3050 Some(x) => x.parse::<u32>()?,
3051 };
3052 let mut rtpmap = SdpAttributeRtpmap::new(payload_type, name, frequency);
3053 if let Some(x) = parameters.next() {
3054 rtpmap.set_channels(x.parse::<u32>()?)
3055 };
3056 Ok(SdpAttribute::Rtpmap(rtpmap))
3057}
3058
3059fn parse_rtcp(to_parse: &str) -> Result<SdpAttribute, SdpParserInternalError> {
3065 let mut tokens = to_parse.split_whitespace();
3066 let port = match tokens.next() {
3067 None => {
3068 return Err(SdpParserInternalError::Generic(
3069 "Rtcp attribute is missing port number".to_string(),
3070 ));
3071 }
3072 Some(x) => x.parse::<u16>()?,
3073 };
3074 let mut rtcp = SdpAttributeRtcp::new(port);
3075 match tokens.next() {
3076 None => (),
3077 Some(x) => {
3078 parse_network_type(x)?;
3079 match tokens.next() {
3080 None => {
3081 return Err(SdpParserInternalError::Generic(
3082 "Rtcp attribute is missing address type token".to_string(),
3083 ));
3084 }
3085 Some(x) => {
3086 let addrtype = AddressType::from_str(x)?;
3087 let addr = match tokens.next() {
3088 None => {
3089 return Err(SdpParserInternalError::Generic(
3090 "Rtcp attribute is missing ip address token".to_string(),
3091 ));
3092 }
3093 Some(x) => match ExplicitlyTypedAddress::try_from((addrtype, x)) {
3094 Ok(address) => address,
3095 Err(e) => return Err(e),
3096 },
3097 };
3098 rtcp.set_addr(addr);
3099 }
3100 };
3101 }
3102 };
3103 Ok(SdpAttribute::Rtcp(rtcp))
3104}
3105
3106fn parse_rtcp_fb(to_parse: &str) -> Result<SdpAttribute, SdpParserInternalError> {
3137 let tokens: Vec<&str> = to_parse.splitn(4, ' ').collect();
3138
3139 let feedback_type = match tokens.get(1) {
3141 Some(x) => match *x {
3142 "ack" => SdpAttributeRtcpFbType::Ack,
3143 "ccm" => SdpAttributeRtcpFbType::Ccm,
3144 "nack" => SdpAttributeRtcpFbType::Nack,
3145 "trr-int" => SdpAttributeRtcpFbType::TrrInt,
3146 "goog-remb" => SdpAttributeRtcpFbType::Remb,
3147 "transport-cc" => SdpAttributeRtcpFbType::TransCc,
3148 _ => {
3149 return Err(SdpParserInternalError::Unsupported(format!(
3150 "Unknown rtcpfb feedback type: {x:?}"
3151 )));
3152 }
3153 },
3154 None => {
3155 return Err(SdpParserInternalError::Generic(
3156 "Error parsing rtcpfb: no feedback type".to_string(),
3157 ));
3158 }
3159 };
3160
3161 let parameter = match feedback_type {
3163 SdpAttributeRtcpFbType::Ack => match tokens.get(2) {
3164 Some(x) => match *x {
3165 "rpsi" | "app" => (*x).to_string(),
3166 _ => {
3167 return Err(SdpParserInternalError::Unsupported(format!(
3168 "Unknown rtcpfb ack parameter: {x:?}"
3169 )));
3170 }
3171 },
3172 None => {
3173 return Err(SdpParserInternalError::Unsupported(
3174 "The rtcpfb ack feeback type needs a parameter:".to_string(),
3175 ));
3176 }
3177 },
3178 SdpAttributeRtcpFbType::Ccm => match tokens.get(2) {
3179 Some(x) => match *x {
3180 "fir" | "tmmbr" | "tstr" | "vbcm" => (*x).to_string(),
3181 _ => {
3182 return Err(SdpParserInternalError::Unsupported(format!(
3183 "Unknown rtcpfb ccm parameter: {x:?}"
3184 )));
3185 }
3186 },
3187 None => "".to_string(),
3188 },
3189 SdpAttributeRtcpFbType::Nack => match tokens.get(2) {
3190 Some(x) => match *x {
3191 "sli" | "pli" | "rpsi" | "app" => (*x).to_string(),
3192 _ => {
3193 return Err(SdpParserInternalError::Unsupported(format!(
3194 "Unknown rtcpfb nack parameter: {x:?}"
3195 )));
3196 }
3197 },
3198 None => "".to_string(),
3199 },
3200 SdpAttributeRtcpFbType::TrrInt => match tokens.get(2) {
3201 Some(x) => match x {
3202 _ if x.parse::<u32>().is_ok() => (*x).to_string(),
3203 _ => {
3204 return Err(SdpParserInternalError::Generic(format!(
3205 "Unknown rtcpfb trr-int parameter: {x:?}"
3206 )));
3207 }
3208 },
3209 None => {
3210 return Err(SdpParserInternalError::Generic(
3211 "The rtcpfb trr-int feedback type needs a parameter".to_string(),
3212 ));
3213 }
3214 },
3215 SdpAttributeRtcpFbType::Remb | SdpAttributeRtcpFbType::TransCc => match tokens.get(2) {
3216 Some(x) => {
3217 return Err(SdpParserInternalError::Unsupported(format!(
3218 "Unknown rtcpfb {feedback_type} parameter: {x:?}"
3219 )));
3220 }
3221 None => "".to_string(),
3222 },
3223 };
3224
3225 Ok(SdpAttribute::Rtcpfb(SdpAttributeRtcpFb {
3226 payload_type: parse_payload_type(tokens[0])?,
3227 feedback_type,
3228 parameter,
3229 extra: match tokens.get(3) {
3230 Some(x) => (*x).to_string(),
3231 None => "".to_string(),
3232 },
3233 }))
3234}
3235
3236fn parse_sctpmap(to_parse: &str) -> Result<SdpAttribute, SdpParserInternalError> {
3249 let tokens: Vec<&str> = to_parse.split_whitespace().collect();
3250 if tokens.len() != 3 {
3251 return Err(SdpParserInternalError::Generic(
3252 "Sctpmap needs to have three tokens".to_string(),
3253 ));
3254 }
3255 let port = tokens[0].parse::<u16>()?;
3256 if tokens[1].to_lowercase() != "webrtc-datachannel" {
3257 return Err(SdpParserInternalError::Generic(
3258 "Unsupported sctpmap type token".to_string(),
3259 ));
3260 }
3261 Ok(SdpAttribute::Sctpmap(SdpAttributeSctpmap {
3262 port,
3263 channels: tokens[2].parse::<u32>()?,
3264 }))
3265}
3266
3267fn parse_setup(to_parse: &str) -> Result<SdpAttribute, SdpParserInternalError> {
3273 Ok(SdpAttribute::Setup(
3274 match to_parse.to_lowercase().as_ref() {
3275 "active" => SdpAttributeSetup::Active,
3276 "actpass" => SdpAttributeSetup::Actpass,
3277 "holdconn" => SdpAttributeSetup::Holdconn,
3278 "passive" => SdpAttributeSetup::Passive,
3279 _ => {
3280 return Err(SdpParserInternalError::Generic(
3281 "Unsupported setup value".to_string(),
3282 ));
3283 }
3284 },
3285 ))
3286}
3287
3288fn parse_simulcast_version_list(
3289 to_parse: &str,
3290) -> Result<Vec<SdpAttributeSimulcastVersion>, SdpParserInternalError> {
3291 let make_version_list = |to_parse: &str| {
3292 to_parse
3293 .split(';')
3294 .map(SdpAttributeSimulcastVersion::new)
3295 .collect()
3296 };
3297 if to_parse.contains('=') {
3298 let mut descriptor_versionlist_pair = to_parse.splitn(2, '=');
3299 match descriptor_versionlist_pair.next().unwrap() {
3300 "rid" => Ok(make_version_list(
3302 descriptor_versionlist_pair.next().unwrap(),
3303 )),
3304 descriptor => Err(SdpParserInternalError::Generic(format!(
3305 "Simulcast attribute has unknown list descriptor '{descriptor:?}'"
3306 ))),
3307 }
3308 } else {
3309 Ok(make_version_list(to_parse))
3310 }
3311}
3312
3313fn parse_simulcast(to_parse: &str) -> Result<SdpAttribute, SdpParserInternalError> {
3339 let mut tokens = to_parse.split_whitespace();
3341 let first_direction = match tokens.next() {
3342 Some(x) => parse_single_direction(x)?,
3343 None => {
3344 return Err(SdpParserInternalError::Generic(
3345 "Simulcast attribute is missing send/recv value".to_string(),
3346 ));
3347 }
3348 };
3349
3350 let first_version_list = match tokens.next() {
3351 Some(x) => parse_simulcast_version_list(x)?,
3352 None => {
3353 return Err(SdpParserInternalError::Generic(
3354 "Simulcast attribute must have an alternatives list after the direction token"
3355 .to_string(),
3356 ));
3357 }
3358 };
3359
3360 let mut second_version_list = Vec::new();
3361 if let Some(x) = tokens.next() {
3362 if parse_single_direction(x)? == first_direction {
3363 return Err(SdpParserInternalError::Generic(
3364 "Simulcast attribute has defined two times the same direction".to_string(),
3365 ));
3366 }
3367
3368 second_version_list = match tokens.next() {
3369 Some(x) => parse_simulcast_version_list(x)?,
3370 None => {
3371 return Err(SdpParserInternalError::Generic(format!(
3372 "{:?}{:?}",
3373 "Simulcast has defined a second direction but",
3374 "no second list of simulcast stream versions"
3375 )));
3376 }
3377 }
3378 }
3379
3380 Ok(SdpAttribute::Simulcast(match first_direction {
3381 SdpSingleDirection::Send => SdpAttributeSimulcast {
3382 send: first_version_list,
3383 receive: second_version_list,
3384 },
3385 SdpSingleDirection::Recv => SdpAttributeSimulcast {
3386 send: second_version_list,
3387 receive: first_version_list,
3388 },
3389 }))
3390}
3391
3392fn parse_ssrc(to_parse: &str) -> Result<SdpAttribute, SdpParserInternalError> {
3401 let mut tokens = to_parse.splitn(2, ' ');
3402 let ssrc_id = match tokens.next() {
3403 None => {
3404 return Err(SdpParserInternalError::Generic(
3405 "Ssrc attribute is missing ssrc-id value".to_string(),
3406 ));
3407 }
3408 Some(x) => x.parse::<u32>()?,
3409 };
3410 let mut ssrc = SdpAttributeSsrc::new(ssrc_id);
3411 match tokens.next() {
3412 None => (),
3413 Some(x) => ssrc.set_attribute(x),
3414 };
3415 Ok(SdpAttribute::Ssrc(ssrc))
3416}
3417
3418pub fn parse_attribute(value: &str) -> Result<SdpType, SdpParserInternalError> {
3419 Ok(SdpType::Attribute(value.trim().parse()?))
3420}
3421
3422#[cfg(test)]
3423#[path = "./attribute_type_tests.rs"]
3424mod tests;