1use std::collections::HashMap;
2use std::convert::TryFrom;
3use std::time::{Duration, SystemTime, UNIX_EPOCH};
4use std::{fmt, io};
5
6use url::Url;
7
8use crate::lexer::*;
9use crate::util::*;
10use shared::error::{Error, Result};
11
12use super::common::*;
13use super::media::*;
14
15pub const ATTR_KEY_CANDIDATE: &str = "candidate";
17pub const ATTR_KEY_END_OF_CANDIDATES: &str = "end-of-candidates";
18pub const ATTR_KEY_IDENTITY: &str = "identity";
19pub const ATTR_KEY_GROUP: &str = "group";
20pub const ATTR_KEY_SSRC: &str = "ssrc";
21pub const ATTR_KEY_SSRC_GROUP: &str = "ssrc-group";
22pub const ATTR_KEY_MSID: &str = "msid";
23pub const ATTR_KEY_MSID_SEMANTIC: &str = "msid-semantic";
24pub const ATTR_KEY_CONNECTION_SETUP: &str = "setup";
25pub const ATTR_KEY_MID: &str = "mid";
26pub const ATTR_KEY_ICELITE: &str = "ice-lite";
27pub const ATTR_KEY_RTCPMUX: &str = "rtcp-mux";
28pub const ATTR_KEY_RTCPRSIZE: &str = "rtcp-rsize";
29pub const ATTR_KEY_INACTIVE: &str = "inactive";
30pub const ATTR_KEY_RECV_ONLY: &str = "recvonly";
31pub const ATTR_KEY_SEND_ONLY: &str = "sendonly";
32pub const ATTR_KEY_SEND_RECV: &str = "sendrecv";
33pub const ATTR_KEY_EXT_MAP: &str = "extmap";
34pub const ATTR_KEY_EXTMAP_ALLOW_MIXED: &str = "extmap-allow-mixed";
35pub const ATTR_KEY_MAX_MESSAGE_SIZE: &str = "max-message-size";
36
37pub const SEMANTIC_TOKEN_LIP_SYNCHRONIZATION: &str = "LS";
39pub const SEMANTIC_TOKEN_FLOW_IDENTIFICATION: &str = "FID";
40pub const SEMANTIC_TOKEN_FORWARD_ERROR_CORRECTION: &str = "FEC";
41pub const SEMANTIC_TOKEN_FORWARD_ERROR_CORRECTION_FRAMEWORK: &str = "FEC-FR";
43pub const SEMANTIC_TOKEN_WEBRTC_MEDIA_STREAMS: &str = "WMS";
44
45pub type Version = isize;
48
49#[derive(Debug, Default, Clone)]
52pub struct Origin {
53 pub username: String,
54 pub session_id: u64,
55 pub session_version: u64,
56 pub network_type: String,
57 pub address_type: String,
58 pub unicast_address: String,
59}
60
61impl fmt::Display for Origin {
62 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
63 write!(
64 f,
65 "{} {} {} {} {} {}",
66 self.username,
67 self.session_id,
68 self.session_version,
69 self.network_type,
70 self.address_type,
71 self.unicast_address,
72 )
73 }
74}
75
76impl Origin {
77 pub fn new() -> Self {
78 Origin {
79 username: "".to_owned(),
80 session_id: 0,
81 session_version: 0,
82 network_type: "".to_owned(),
83 address_type: "".to_owned(),
84 unicast_address: "".to_owned(),
85 }
86 }
87}
88
89pub type SessionName = String;
92
93pub type EmailAddress = String;
97
98pub type PhoneNumber = String;
102
103#[derive(Debug, Default, Clone)]
106pub struct TimeZone {
107 pub adjustment_time: u64,
108 pub offset: i64,
109}
110
111impl fmt::Display for TimeZone {
112 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
113 write!(f, "{} {}", self.adjustment_time, self.offset)
114 }
115}
116
117#[derive(Debug, Default, Clone)]
121pub struct TimeDescription {
122 pub timing: Timing,
126
127 pub repeat_times: Vec<RepeatTime>,
131}
132
133#[derive(Debug, Default, Clone)]
136pub struct Timing {
137 pub start_time: u64,
138 pub stop_time: u64,
139}
140
141impl fmt::Display for Timing {
142 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
143 write!(f, "{} {}", self.start_time, self.stop_time)
144 }
145}
146
147#[derive(Debug, Default, Clone)]
150pub struct RepeatTime {
151 pub interval: i64,
152 pub duration: i64,
153 pub offsets: Vec<i64>,
154}
155
156impl fmt::Display for RepeatTime {
157 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
158 write!(f, "{} {}", self.interval, self.duration)?;
159
160 for value in &self.offsets {
161 write!(f, " {value}")?;
162 }
163 Ok(())
164 }
165}
166
167#[derive(Debug, Default, Clone)]
170pub struct SessionDescription {
171 pub version: Version,
175
176 pub origin: Origin,
180
181 pub session_name: SessionName,
185
186 pub session_information: Option<Information>,
190
191 pub uri: Option<Url>,
195
196 pub email_address: Option<EmailAddress>,
200
201 pub phone_number: Option<PhoneNumber>,
205
206 pub connection_information: Option<ConnectionInformation>,
210
211 pub bandwidth: Vec<Bandwidth>,
215
216 pub time_descriptions: Vec<TimeDescription>,
219
220 pub time_zones: Vec<TimeZone>,
224
225 pub encryption_key: Option<EncryptionKey>,
231
232 pub attributes: Vec<Attribute>,
238
239 pub media_descriptions: Vec<MediaDescription>,
241}
242
243impl fmt::Display for SessionDescription {
244 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
245 write_key_value(f, "v=", Some(&self.version))?;
246 write_key_value(f, "o=", Some(&self.origin))?;
247 write_key_value(f, "s=", Some(&self.session_name))?;
248
249 write_key_value(f, "i=", self.session_information.as_ref())?;
250
251 if let Some(uri) = &self.uri {
252 write_key_value(f, "u=", Some(uri))?;
253 }
254 write_key_value(f, "e=", self.email_address.as_ref())?;
255 write_key_value(f, "p=", self.phone_number.as_ref())?;
256 if let Some(connection_information) = &self.connection_information {
257 write_key_value(f, "c=", Some(&connection_information))?;
258 }
259
260 for bandwidth in &self.bandwidth {
261 write_key_value(f, "b=", Some(&bandwidth))?;
262 }
263 for time_description in &self.time_descriptions {
264 write_key_value(f, "t=", Some(&time_description.timing))?;
265 for repeat_time in &time_description.repeat_times {
266 write_key_value(f, "r=", Some(&repeat_time))?;
267 }
268 }
269
270 write_key_slice_of_values(f, "z=", &self.time_zones)?;
271
272 write_key_value(f, "k=", self.encryption_key.as_ref())?;
273 for attribute in &self.attributes {
274 write_key_value(f, "a=", Some(&attribute))?;
275 }
276
277 for media_description in &self.media_descriptions {
278 write_key_value(f, "m=", Some(&media_description.media_name))?;
279 write_key_value(f, "i=", media_description.media_title.as_ref())?;
280 if let Some(connection_information) = &media_description.connection_information {
281 write_key_value(f, "c=", Some(&connection_information))?;
282 }
283 for bandwidth in &media_description.bandwidth {
284 write_key_value(f, "b=", Some(&bandwidth))?;
285 }
286 write_key_value(f, "k=", media_description.encryption_key.as_ref())?;
287 for attribute in &media_description.attributes {
288 write_key_value(f, "a=", Some(&attribute))?;
289 }
290 }
291
292 Ok(())
293 }
294}
295
296impl SessionDescription {
298 pub fn new_jsep_session_description(identity: bool) -> Self {
303 let d = SessionDescription {
304 version: 0,
305 origin: Origin {
306 username: "-".to_string(),
307 session_id: new_session_id(),
308 session_version: SystemTime::now()
309 .duration_since(UNIX_EPOCH)
310 .unwrap_or_else(|_| Duration::from_secs(0))
311 .subsec_nanos() as u64,
312 network_type: "IN".to_string(),
313 address_type: "IP4".to_string(),
314 unicast_address: "0.0.0.0".to_string(),
315 },
316 session_name: "-".to_string(),
317 session_information: None,
318 uri: None,
319 email_address: None,
320 phone_number: None,
321 connection_information: None,
322 bandwidth: vec![],
323 time_descriptions: vec![TimeDescription {
324 timing: Timing {
325 start_time: 0,
326 stop_time: 0,
327 },
328 repeat_times: vec![],
329 }],
330 time_zones: vec![],
331 encryption_key: None,
332 attributes: vec![], media_descriptions: vec![],
334 };
335
336 if identity {
337 d.with_property_attribute(ATTR_KEY_IDENTITY.to_string())
338 } else {
339 d
340 }
341 }
342
343 pub fn with_property_attribute(mut self, key: String) -> Self {
345 self.attributes.push(Attribute::new(key, None));
346 self
347 }
348
349 pub fn with_value_attribute(mut self, key: String, value: String) -> Self {
351 self.attributes.push(Attribute::new(key, Some(value)));
352 self
353 }
354
355 pub fn with_fingerprint(self, algorithm: String, value: String) -> Self {
357 self.with_value_attribute("fingerprint".to_string(), algorithm + " " + value.as_str())
358 }
359
360 pub fn with_media(mut self, md: MediaDescription) -> Self {
362 self.media_descriptions.push(md);
363 self
364 }
365
366 fn build_codec_map(&self) -> HashMap<u8, Codec> {
367 let mut codecs: HashMap<u8, Codec> = HashMap::new();
368
369 for m in &self.media_descriptions {
370 for a in &m.attributes {
371 let attr = a.to_string();
372 if attr.starts_with("rtpmap:") {
373 if let Ok(codec) = parse_rtpmap(&attr) {
374 merge_codecs(codec, &mut codecs);
375 }
376 } else if attr.starts_with("fmtp:") {
377 if let Ok(codec) = parse_fmtp(&attr) {
378 merge_codecs(codec, &mut codecs);
379 }
380 } else if attr.starts_with("rtcp-fb:")
381 && let Ok(codec) = parse_rtcp_fb(&attr)
382 {
383 merge_codecs(codec, &mut codecs);
384 }
385 }
386 }
387
388 codecs
389 }
390
391 pub fn get_codec_for_payload_type(&self, payload_type: u8) -> Result<Codec> {
393 let codecs = self.build_codec_map();
394
395 if let Some(codec) = codecs.get(&payload_type) {
396 Ok(codec.clone())
397 } else {
398 Err(Error::PayloadTypeNotFound)
399 }
400 }
401
402 pub fn get_payload_type_for_codec(&self, wanted: &Codec) -> Result<u8> {
405 let codecs = self.build_codec_map();
406
407 for (payload_type, codec) in codecs.iter() {
408 if codecs_match(wanted, codec) {
409 return Ok(*payload_type);
410 }
411 }
412
413 Err(Error::CodecNotFound)
414 }
415
416 pub fn has_attribute(&self, key: &str) -> bool {
418 self.attributes.iter().any(|a| a.key == key)
419 }
420
421 pub fn attribute(&self, key: &str) -> Option<&String> {
423 for a in &self.attributes {
424 if a.key == key {
425 return a.value.as_ref();
426 }
427 }
428 None
429 }
430
431 pub fn marshal(&self) -> String {
465 self.to_string()
466 }
467
468 pub fn unmarshal<R: io::BufRead + io::Seek>(reader: &mut R) -> Result<Self> {
547 let mut lexer = Lexer {
548 desc: SessionDescription {
549 version: 0,
550 origin: Origin::new(),
551 session_name: "".to_owned(),
552 session_information: None,
553 uri: None,
554 email_address: None,
555 phone_number: None,
556 connection_information: None,
557 bandwidth: vec![],
558 time_descriptions: vec![],
559 time_zones: vec![],
560 encryption_key: None,
561 attributes: vec![],
562 media_descriptions: vec![],
563 },
564 reader,
565 };
566
567 let mut state = Some(StateFn { f: s1 });
568 while let Some(s) = state {
569 state = (s.f)(&mut lexer)?;
570 }
571
572 Ok(lexer.desc)
573 }
574}
575
576impl From<SessionDescription> for String {
577 fn from(sdp: SessionDescription) -> String {
578 sdp.marshal()
579 }
580}
581
582impl TryFrom<String> for SessionDescription {
583 type Error = Error;
584 fn try_from(sdp_string: String) -> Result<Self> {
585 let mut reader = io::Cursor::new(sdp_string.as_bytes());
586 let session_description = SessionDescription::unmarshal(&mut reader)?;
587 Ok(session_description)
588 }
589}
590
591fn s1<'a, R: io::BufRead + io::Seek>(lexer: &mut Lexer<'a, R>) -> Result<Option<StateFn<'a, R>>> {
592 let (key, _) = read_type(lexer.reader)?;
593 if &key == b"v=" {
594 return Ok(Some(StateFn {
595 f: unmarshal_protocol_version,
596 }));
597 }
598
599 Err(Error::SdpInvalidSyntax(String::from_utf8(key)?))
600}
601
602fn s2<'a, R: io::BufRead + io::Seek>(lexer: &mut Lexer<'a, R>) -> Result<Option<StateFn<'a, R>>> {
603 let (key, _) = read_type(lexer.reader)?;
604 if &key == b"o=" {
605 return Ok(Some(StateFn {
606 f: unmarshal_origin,
607 }));
608 }
609
610 Err(Error::SdpInvalidSyntax(String::from_utf8(key)?))
611}
612
613fn s3<'a, R: io::BufRead + io::Seek>(lexer: &mut Lexer<'a, R>) -> Result<Option<StateFn<'a, R>>> {
614 let (key, _) = read_type(lexer.reader)?;
615 if &key == b"s=" {
616 return Ok(Some(StateFn {
617 f: unmarshal_session_name,
618 }));
619 }
620
621 Err(Error::SdpInvalidSyntax(String::from_utf8(key)?))
622}
623
624fn s4<'a, R: io::BufRead + io::Seek>(lexer: &mut Lexer<'a, R>) -> Result<Option<StateFn<'a, R>>> {
625 let (key, _) = read_type(lexer.reader)?;
626 match key.as_slice() {
627 b"i=" => Ok(Some(StateFn {
628 f: unmarshal_session_information,
629 })),
630 b"u=" => Ok(Some(StateFn { f: unmarshal_uri })),
631 b"e=" => Ok(Some(StateFn { f: unmarshal_email })),
632 b"p=" => Ok(Some(StateFn { f: unmarshal_phone })),
633 b"c=" => Ok(Some(StateFn {
634 f: unmarshal_session_connection_information,
635 })),
636 b"b=" => Ok(Some(StateFn {
637 f: unmarshal_session_bandwidth,
638 })),
639 b"t=" => Ok(Some(StateFn {
640 f: unmarshal_timing,
641 })),
642 _ => Err(Error::SdpInvalidSyntax(String::from_utf8(key)?)),
643 }
644}
645
646fn s5<'a, R: io::BufRead + io::Seek>(lexer: &mut Lexer<'a, R>) -> Result<Option<StateFn<'a, R>>> {
647 let (key, _) = read_type(lexer.reader)?;
648 match key.as_slice() {
649 b"b=" => Ok(Some(StateFn {
650 f: unmarshal_session_bandwidth,
651 })),
652 b"t=" => Ok(Some(StateFn {
653 f: unmarshal_timing,
654 })),
655 _ => Err(Error::SdpInvalidSyntax(String::from_utf8(key)?)),
656 }
657}
658
659fn s6<'a, R: io::BufRead + io::Seek>(lexer: &mut Lexer<'a, R>) -> Result<Option<StateFn<'a, R>>> {
660 let (key, _) = read_type(lexer.reader)?;
661 match key.as_slice() {
662 b"p=" => Ok(Some(StateFn { f: unmarshal_phone })),
663 b"c=" => Ok(Some(StateFn {
664 f: unmarshal_session_connection_information,
665 })),
666 b"b=" => Ok(Some(StateFn {
667 f: unmarshal_session_bandwidth,
668 })),
669 b"t=" => Ok(Some(StateFn {
670 f: unmarshal_timing,
671 })),
672 _ => Err(Error::SdpInvalidSyntax(String::from_utf8(key)?)),
673 }
674}
675
676fn s7<'a, R: io::BufRead + io::Seek>(lexer: &mut Lexer<'a, R>) -> Result<Option<StateFn<'a, R>>> {
677 let (key, _) = read_type(lexer.reader)?;
678 match key.as_slice() {
679 b"u=" => Ok(Some(StateFn { f: unmarshal_uri })),
680 b"e=" => Ok(Some(StateFn { f: unmarshal_email })),
681 b"p=" => Ok(Some(StateFn { f: unmarshal_phone })),
682 b"c=" => Ok(Some(StateFn {
683 f: unmarshal_session_connection_information,
684 })),
685 b"b=" => Ok(Some(StateFn {
686 f: unmarshal_session_bandwidth,
687 })),
688 b"t=" => Ok(Some(StateFn {
689 f: unmarshal_timing,
690 })),
691 _ => Err(Error::SdpInvalidSyntax(String::from_utf8(key)?)),
692 }
693}
694
695fn s8<'a, R: io::BufRead + io::Seek>(lexer: &mut Lexer<'a, R>) -> Result<Option<StateFn<'a, R>>> {
696 let (key, _) = read_type(lexer.reader)?;
697 match key.as_slice() {
698 b"c=" => Ok(Some(StateFn {
699 f: unmarshal_session_connection_information,
700 })),
701 b"b=" => Ok(Some(StateFn {
702 f: unmarshal_session_bandwidth,
703 })),
704 b"t=" => Ok(Some(StateFn {
705 f: unmarshal_timing,
706 })),
707 _ => Err(Error::SdpInvalidSyntax(String::from_utf8(key)?)),
708 }
709}
710
711fn s9<'a, R: io::BufRead + io::Seek>(lexer: &mut Lexer<'a, R>) -> Result<Option<StateFn<'a, R>>> {
712 let (key, num_bytes) = read_type(lexer.reader)?;
713 if key.is_empty() && num_bytes == 0 {
714 return Ok(None);
715 }
716
717 match key.as_slice() {
718 b"z=" => Ok(Some(StateFn {
719 f: unmarshal_time_zones,
720 })),
721 b"k=" => Ok(Some(StateFn {
722 f: unmarshal_session_encryption_key,
723 })),
724 b"a=" => Ok(Some(StateFn {
725 f: unmarshal_session_attribute,
726 })),
727 b"r=" => Ok(Some(StateFn {
728 f: unmarshal_repeat_times,
729 })),
730 b"t=" => Ok(Some(StateFn {
731 f: unmarshal_timing,
732 })),
733 b"m=" => Ok(Some(StateFn {
734 f: unmarshal_media_description,
735 })),
736 _ => Err(Error::SdpInvalidSyntax(String::from_utf8(key)?)),
737 }
738}
739
740fn s10<'a, R: io::BufRead + io::Seek>(lexer: &mut Lexer<'a, R>) -> Result<Option<StateFn<'a, R>>> {
741 let (key, _) = read_type(lexer.reader)?;
742 match key.as_slice() {
743 b"e=" => Ok(Some(StateFn { f: unmarshal_email })),
744 b"p=" => Ok(Some(StateFn { f: unmarshal_phone })),
745 b"c=" => Ok(Some(StateFn {
746 f: unmarshal_session_connection_information,
747 })),
748 b"b=" => Ok(Some(StateFn {
749 f: unmarshal_session_bandwidth,
750 })),
751 b"t=" => Ok(Some(StateFn {
752 f: unmarshal_timing,
753 })),
754 _ => Err(Error::SdpInvalidSyntax(String::from_utf8(key)?)),
755 }
756}
757
758fn s11<'a, R: io::BufRead + io::Seek>(lexer: &mut Lexer<'a, R>) -> Result<Option<StateFn<'a, R>>> {
759 let (key, num_bytes) = read_type(lexer.reader)?;
760 if key.is_empty() && num_bytes == 0 {
761 return Ok(None);
762 }
763
764 match key.as_slice() {
765 b"a=" => Ok(Some(StateFn {
766 f: unmarshal_session_attribute,
767 })),
768 b"m=" => Ok(Some(StateFn {
769 f: unmarshal_media_description,
770 })),
771 _ => Err(Error::SdpInvalidSyntax(String::from_utf8(key)?)),
772 }
773}
774
775fn s12<'a, R: io::BufRead + io::Seek>(lexer: &mut Lexer<'a, R>) -> Result<Option<StateFn<'a, R>>> {
776 let (key, num_bytes) = read_type(lexer.reader)?;
777 if key.is_empty() && num_bytes == 0 {
778 return Ok(None);
779 }
780
781 match key.as_slice() {
782 b"a=" => Ok(Some(StateFn {
783 f: unmarshal_media_attribute,
784 })),
785 b"k=" => Ok(Some(StateFn {
786 f: unmarshal_media_encryption_key,
787 })),
788 b"b=" => Ok(Some(StateFn {
789 f: unmarshal_media_bandwidth,
790 })),
791 b"c=" => Ok(Some(StateFn {
792 f: unmarshal_media_connection_information,
793 })),
794 b"i=" => Ok(Some(StateFn {
795 f: unmarshal_media_title,
796 })),
797 b"m=" => Ok(Some(StateFn {
798 f: unmarshal_media_description,
799 })),
800 _ => Err(Error::SdpInvalidSyntax(String::from_utf8(key)?)),
801 }
802}
803
804fn s13<'a, R: io::BufRead + io::Seek>(lexer: &mut Lexer<'a, R>) -> Result<Option<StateFn<'a, R>>> {
805 let (key, num_bytes) = read_type(lexer.reader)?;
806 if key.is_empty() && num_bytes == 0 {
807 return Ok(None);
808 }
809
810 match key.as_slice() {
811 b"a=" => Ok(Some(StateFn {
812 f: unmarshal_session_attribute,
813 })),
814 b"k=" => Ok(Some(StateFn {
815 f: unmarshal_session_encryption_key,
816 })),
817 b"m=" => Ok(Some(StateFn {
818 f: unmarshal_media_description,
819 })),
820 _ => Err(Error::SdpInvalidSyntax(String::from_utf8(key)?)),
821 }
822}
823
824fn s14<'a, R: io::BufRead + io::Seek>(lexer: &mut Lexer<'a, R>) -> Result<Option<StateFn<'a, R>>> {
825 let (key, num_bytes) = read_type(lexer.reader)?;
826 if key.is_empty() && num_bytes == 0 {
827 return Ok(None);
828 }
829
830 match key.as_slice() {
831 b"a=" => Ok(Some(StateFn {
832 f: unmarshal_media_attribute,
833 })),
834 b"k=" => Ok(Some(StateFn {
836 f: unmarshal_media_encryption_key,
837 })),
838 b"b=" => Ok(Some(StateFn {
840 f: unmarshal_media_bandwidth,
841 })),
842 b"c=" => Ok(Some(StateFn {
844 f: unmarshal_media_connection_information,
845 })),
846 b"i=" => Ok(Some(StateFn {
848 f: unmarshal_media_title,
849 })),
850 b"m=" => Ok(Some(StateFn {
851 f: unmarshal_media_description,
852 })),
853 _ => Err(Error::SdpInvalidSyntax(String::from_utf8(key)?)),
854 }
855}
856
857fn s15<'a, R: io::BufRead + io::Seek>(lexer: &mut Lexer<'a, R>) -> Result<Option<StateFn<'a, R>>> {
858 let (key, num_bytes) = read_type(lexer.reader)?;
859 if key.is_empty() && num_bytes == 0 {
860 return Ok(None);
861 }
862
863 match key.as_slice() {
864 b"a=" => Ok(Some(StateFn {
865 f: unmarshal_media_attribute,
866 })),
867 b"k=" => Ok(Some(StateFn {
868 f: unmarshal_media_encryption_key,
869 })),
870 b"b=" => Ok(Some(StateFn {
871 f: unmarshal_media_bandwidth,
872 })),
873 b"c=" => Ok(Some(StateFn {
874 f: unmarshal_media_connection_information,
875 })),
876 b"i=" => Ok(Some(StateFn {
878 f: unmarshal_media_title,
879 })),
880 b"m=" => Ok(Some(StateFn {
881 f: unmarshal_media_description,
882 })),
883 _ => Err(Error::SdpInvalidSyntax(String::from_utf8(key)?)),
884 }
885}
886
887fn s16<'a, R: io::BufRead + io::Seek>(lexer: &mut Lexer<'a, R>) -> Result<Option<StateFn<'a, R>>> {
888 let (key, num_bytes) = read_type(lexer.reader)?;
889 if key.is_empty() && num_bytes == 0 {
890 return Ok(None);
891 }
892
893 match key.as_slice() {
894 b"a=" => Ok(Some(StateFn {
895 f: unmarshal_media_attribute,
896 })),
897 b"k=" => Ok(Some(StateFn {
898 f: unmarshal_media_encryption_key,
899 })),
900 b"c=" => Ok(Some(StateFn {
901 f: unmarshal_media_connection_information,
902 })),
903 b"b=" => Ok(Some(StateFn {
904 f: unmarshal_media_bandwidth,
905 })),
906 b"i=" => Ok(Some(StateFn {
908 f: unmarshal_media_title,
909 })),
910 b"m=" => Ok(Some(StateFn {
911 f: unmarshal_media_description,
912 })),
913 _ => Err(Error::SdpInvalidSyntax(String::from_utf8(key)?)),
914 }
915}
916
917fn unmarshal_protocol_version<'a, R: io::BufRead + io::Seek>(
918 lexer: &mut Lexer<'a, R>,
919) -> Result<Option<StateFn<'a, R>>> {
920 let (value, _) = read_value(lexer.reader)?;
921
922 let version = value.parse::<u32>()?;
923
924 if version != 0 {
927 return Err(Error::SdpInvalidSyntax(value));
928 }
929
930 Ok(Some(StateFn { f: s2 }))
931}
932
933fn unmarshal_origin<'a, R: io::BufRead + io::Seek>(
934 lexer: &mut Lexer<'a, R>,
935) -> Result<Option<StateFn<'a, R>>> {
936 let (value, _) = read_value(lexer.reader)?;
937
938 let fields: Vec<&str> = value.split_whitespace().collect();
939 if fields.len() != 6 {
940 return Err(Error::SdpInvalidSyntax(format!("`o={value}`")));
941 }
942
943 let session_id = fields[1].parse::<u64>()?;
944 let session_version = fields[2].parse::<u64>()?;
945
946 let i = index_of(fields[3], &["IN"]);
949 if i == -1 {
950 return Err(Error::SdpInvalidValue(fields[3].to_owned()));
951 }
952
953 let i = index_of(fields[4], &["IP4", "IP6"]);
956 if i == -1 {
957 return Err(Error::SdpInvalidValue(fields[4].to_owned()));
958 }
959
960 lexer.desc.origin = Origin {
963 username: fields[0].to_owned(),
964 session_id,
965 session_version,
966 network_type: fields[3].to_owned(),
967 address_type: fields[4].to_owned(),
968 unicast_address: fields[5].to_owned(),
969 };
970
971 Ok(Some(StateFn { f: s3 }))
972}
973
974fn unmarshal_session_name<'a, R: io::BufRead + io::Seek>(
975 lexer: &mut Lexer<'a, R>,
976) -> Result<Option<StateFn<'a, R>>> {
977 let (value, _) = read_value(lexer.reader)?;
978 lexer.desc.session_name = value;
979 Ok(Some(StateFn { f: s4 }))
980}
981
982fn unmarshal_session_information<'a, R: io::BufRead + io::Seek>(
983 lexer: &mut Lexer<'a, R>,
984) -> Result<Option<StateFn<'a, R>>> {
985 let (value, _) = read_value(lexer.reader)?;
986 lexer.desc.session_information = Some(value);
987 Ok(Some(StateFn { f: s7 }))
988}
989
990fn unmarshal_uri<'a, R: io::BufRead + io::Seek>(
991 lexer: &mut Lexer<'a, R>,
992) -> Result<Option<StateFn<'a, R>>> {
993 let (value, _) = read_value(lexer.reader)?;
994 lexer.desc.uri = Some(Url::parse(&value)?);
995 Ok(Some(StateFn { f: s10 }))
996}
997
998fn unmarshal_email<'a, R: io::BufRead + io::Seek>(
999 lexer: &mut Lexer<'a, R>,
1000) -> Result<Option<StateFn<'a, R>>> {
1001 let (value, _) = read_value(lexer.reader)?;
1002 lexer.desc.email_address = Some(value);
1003 Ok(Some(StateFn { f: s6 }))
1004}
1005
1006fn unmarshal_phone<'a, R: io::BufRead + io::Seek>(
1007 lexer: &mut Lexer<'a, R>,
1008) -> Result<Option<StateFn<'a, R>>> {
1009 let (value, _) = read_value(lexer.reader)?;
1010 lexer.desc.phone_number = Some(value);
1011 Ok(Some(StateFn { f: s8 }))
1012}
1013
1014fn unmarshal_session_connection_information<'a, R: io::BufRead + io::Seek>(
1015 lexer: &mut Lexer<'a, R>,
1016) -> Result<Option<StateFn<'a, R>>> {
1017 let (value, _) = read_value(lexer.reader)?;
1018 lexer.desc.connection_information = unmarshal_connection_information(&value)?;
1019 Ok(Some(StateFn { f: s5 }))
1020}
1021
1022fn unmarshal_connection_information(value: &str) -> Result<Option<ConnectionInformation>> {
1023 let fields: Vec<&str> = value.split_whitespace().collect();
1024 if fields.len() < 2 {
1025 return Err(Error::SdpInvalidSyntax(format!("`c={value}`")));
1026 }
1027
1028 let i = index_of(fields[0], &["IN"]);
1031 if i == -1 {
1032 return Err(Error::SdpInvalidValue(fields[0].to_owned()));
1033 }
1034
1035 let i = index_of(fields[1], &["IP4", "IP6"]);
1038 if i == -1 {
1039 return Err(Error::SdpInvalidValue(fields[1].to_owned()));
1040 }
1041
1042 let address = if fields.len() > 2 {
1043 Some(Address {
1044 address: fields[2].to_owned(),
1045 ttl: None,
1046 range: None,
1047 })
1048 } else {
1049 None
1050 };
1051
1052 Ok(Some(ConnectionInformation {
1053 network_type: fields[0].to_owned(),
1054 address_type: fields[1].to_owned(),
1055 address,
1056 }))
1057}
1058
1059fn unmarshal_session_bandwidth<'a, R: io::BufRead + io::Seek>(
1060 lexer: &mut Lexer<'a, R>,
1061) -> Result<Option<StateFn<'a, R>>> {
1062 let (value, _) = read_value(lexer.reader)?;
1063 lexer.desc.bandwidth.push(unmarshal_bandwidth(&value)?);
1064 Ok(Some(StateFn { f: s5 }))
1065}
1066
1067fn unmarshal_bandwidth(value: &str) -> Result<Bandwidth> {
1068 let mut parts: Vec<&str> = value.split(':').collect();
1069 if parts.len() != 2 {
1070 return Err(Error::SdpInvalidSyntax(format!("`b={value}`")));
1071 }
1072
1073 let experimental = parts[0].starts_with("X-");
1074 if experimental {
1075 parts[0] = parts[0].trim_start_matches("X-");
1076 } else {
1077 let i = index_of(parts[0], &["CT", "AS", "TIAS"]);
1081 if i == -1 {
1082 return Err(Error::SdpInvalidValue(parts[0].to_owned()));
1083 }
1084 }
1085
1086 let bandwidth = parts[1].parse::<u64>()?;
1087
1088 Ok(Bandwidth {
1089 experimental,
1090 bandwidth_type: parts[0].to_owned(),
1091 bandwidth,
1092 })
1093}
1094
1095fn unmarshal_timing<'a, R: io::BufRead + io::Seek>(
1096 lexer: &mut Lexer<'a, R>,
1097) -> Result<Option<StateFn<'a, R>>> {
1098 let (value, _) = read_value(lexer.reader)?;
1099
1100 let fields: Vec<&str> = value.split_whitespace().collect();
1101 if fields.len() < 2 {
1102 return Err(Error::SdpInvalidSyntax(format!("`t={value}`")));
1103 }
1104
1105 let start_time = fields[0].parse::<u64>()?;
1106 let stop_time = fields[1].parse::<u64>()?;
1107
1108 lexer.desc.time_descriptions.push(TimeDescription {
1109 timing: Timing {
1110 start_time,
1111 stop_time,
1112 },
1113 repeat_times: vec![],
1114 });
1115
1116 Ok(Some(StateFn { f: s9 }))
1117}
1118
1119fn unmarshal_repeat_times<'a, R: io::BufRead + io::Seek>(
1120 lexer: &mut Lexer<'a, R>,
1121) -> Result<Option<StateFn<'a, R>>> {
1122 let (value, _) = read_value(lexer.reader)?;
1123
1124 let fields: Vec<&str> = value.split_whitespace().collect();
1125 if fields.len() < 3 {
1126 return Err(Error::SdpInvalidSyntax(format!("`r={value}`")));
1127 }
1128
1129 if let Some(latest_time_desc) = lexer.desc.time_descriptions.last_mut() {
1130 let interval = parse_time_units(fields[0])?;
1131 let duration = parse_time_units(fields[1])?;
1132 let mut offsets = vec![];
1133 for field in fields.iter().skip(2) {
1134 let offset = parse_time_units(field)?;
1135 offsets.push(offset);
1136 }
1137 latest_time_desc.repeat_times.push(RepeatTime {
1138 interval,
1139 duration,
1140 offsets,
1141 });
1142
1143 Ok(Some(StateFn { f: s9 }))
1144 } else {
1145 Err(Error::SdpEmptyTimeDescription)
1146 }
1147}
1148
1149fn unmarshal_time_zones<'a, R: io::BufRead + io::Seek>(
1150 lexer: &mut Lexer<'a, R>,
1151) -> Result<Option<StateFn<'a, R>>> {
1152 let (value, _) = read_value(lexer.reader)?;
1153
1154 let fields: Vec<&str> = value.split_whitespace().collect();
1158 if !fields.len().is_multiple_of(2) {
1159 return Err(Error::SdpInvalidSyntax(format!("`t={value}`")));
1160 }
1161
1162 for i in (0..fields.len()).step_by(2) {
1163 let adjustment_time = fields[i].parse::<u64>()?;
1164 let offset = parse_time_units(fields[i + 1])?;
1165
1166 lexer.desc.time_zones.push(TimeZone {
1167 adjustment_time,
1168 offset,
1169 });
1170 }
1171
1172 Ok(Some(StateFn { f: s13 }))
1173}
1174
1175fn unmarshal_session_encryption_key<'a, R: io::BufRead + io::Seek>(
1176 lexer: &mut Lexer<'a, R>,
1177) -> Result<Option<StateFn<'a, R>>> {
1178 let (value, _) = read_value(lexer.reader)?;
1179 lexer.desc.encryption_key = Some(value);
1180 Ok(Some(StateFn { f: s11 }))
1181}
1182
1183fn unmarshal_session_attribute<'a, R: io::BufRead + io::Seek>(
1184 lexer: &mut Lexer<'a, R>,
1185) -> Result<Option<StateFn<'a, R>>> {
1186 let (value, _) = read_value(lexer.reader)?;
1187
1188 let fields: Vec<&str> = value.splitn(2, ':').collect();
1189 let attribute = if fields.len() == 2 {
1190 Attribute {
1191 key: fields[0].to_owned(),
1192 value: Some(fields[1].to_owned()),
1193 }
1194 } else {
1195 Attribute {
1196 key: fields[0].to_owned(),
1197 value: None,
1198 }
1199 };
1200 lexer.desc.attributes.push(attribute);
1201
1202 Ok(Some(StateFn { f: s11 }))
1203}
1204
1205fn unmarshal_media_description<'a, R: io::BufRead + io::Seek>(
1206 lexer: &mut Lexer<'a, R>,
1207) -> Result<Option<StateFn<'a, R>>> {
1208 let (value, _) = read_value(lexer.reader)?;
1209
1210 let fields: Vec<&str> = value.split_whitespace().collect();
1211 if fields.len() < 4 {
1212 return Err(Error::SdpInvalidSyntax(format!("`m={value}`")));
1213 }
1214
1215 let i = index_of(
1221 fields[0],
1222 &["audio", "video", "text", "application", "message", "image"],
1223 );
1224 if i == -1 {
1225 return Err(Error::SdpInvalidValue(fields[0].to_owned()));
1226 }
1227
1228 let parts: Vec<&str> = fields[1].split('/').collect();
1230 let port_value = parts[0].parse::<u16>()? as isize;
1231 let port_range = if parts.len() > 1 {
1232 Some(parts[1].parse::<i32>()? as isize)
1233 } else {
1234 None
1235 };
1236
1237 let mut protos = vec![];
1241 for proto in fields[2].split('/').collect::<Vec<&str>>() {
1242 let i = index_of(
1243 proto,
1244 &[
1245 "UDP", "RTP", "AVP", "SAVP", "SAVPF", "TLS", "DTLS", "SCTP", "AVPF", "udptl",
1246 ],
1247 );
1248 if i == -1 {
1249 return Err(Error::SdpInvalidValue(fields[2].to_owned()));
1250 }
1251 protos.push(proto.to_owned());
1252 }
1253
1254 let mut formats = vec![];
1256 for field in fields.iter().skip(3) {
1257 formats.push(field.to_string());
1258 }
1259
1260 lexer.desc.media_descriptions.push(MediaDescription {
1261 media_name: MediaName {
1262 media: fields[0].to_owned(),
1263 port: RangedPort {
1264 value: port_value,
1265 range: port_range,
1266 },
1267 protos,
1268 formats,
1269 },
1270 media_title: None,
1271 connection_information: None,
1272 bandwidth: vec![],
1273 encryption_key: None,
1274 attributes: vec![],
1275 });
1276
1277 Ok(Some(StateFn { f: s12 }))
1278}
1279
1280fn unmarshal_media_title<'a, R: io::BufRead + io::Seek>(
1281 lexer: &mut Lexer<'a, R>,
1282) -> Result<Option<StateFn<'a, R>>> {
1283 let (value, _) = read_value(lexer.reader)?;
1284
1285 if let Some(latest_media_desc) = lexer.desc.media_descriptions.last_mut() {
1286 latest_media_desc.media_title = Some(value);
1287 Ok(Some(StateFn { f: s16 }))
1288 } else {
1289 Err(Error::SdpEmptyTimeDescription)
1290 }
1291}
1292
1293fn unmarshal_media_connection_information<'a, R: io::BufRead + io::Seek>(
1294 lexer: &mut Lexer<'a, R>,
1295) -> Result<Option<StateFn<'a, R>>> {
1296 let (value, _) = read_value(lexer.reader)?;
1297
1298 if let Some(latest_media_desc) = lexer.desc.media_descriptions.last_mut() {
1299 latest_media_desc.connection_information = unmarshal_connection_information(&value)?;
1300 Ok(Some(StateFn { f: s15 }))
1301 } else {
1302 Err(Error::SdpEmptyTimeDescription)
1303 }
1304}
1305
1306fn unmarshal_media_bandwidth<'a, R: io::BufRead + io::Seek>(
1307 lexer: &mut Lexer<'a, R>,
1308) -> Result<Option<StateFn<'a, R>>> {
1309 let (value, _) = read_value(lexer.reader)?;
1310
1311 if let Some(latest_media_desc) = lexer.desc.media_descriptions.last_mut() {
1312 let bandwidth = unmarshal_bandwidth(&value)?;
1313 latest_media_desc.bandwidth.push(bandwidth);
1314 Ok(Some(StateFn { f: s15 }))
1315 } else {
1316 Err(Error::SdpEmptyTimeDescription)
1317 }
1318}
1319
1320fn unmarshal_media_encryption_key<'a, R: io::BufRead + io::Seek>(
1321 lexer: &mut Lexer<'a, R>,
1322) -> Result<Option<StateFn<'a, R>>> {
1323 let (value, _) = read_value(lexer.reader)?;
1324
1325 if let Some(latest_media_desc) = lexer.desc.media_descriptions.last_mut() {
1326 latest_media_desc.encryption_key = Some(value);
1327 Ok(Some(StateFn { f: s14 }))
1328 } else {
1329 Err(Error::SdpEmptyTimeDescription)
1330 }
1331}
1332
1333fn unmarshal_media_attribute<'a, R: io::BufRead + io::Seek>(
1334 lexer: &mut Lexer<'a, R>,
1335) -> Result<Option<StateFn<'a, R>>> {
1336 let (value, _) = read_value(lexer.reader)?;
1337
1338 let fields: Vec<&str> = value.splitn(2, ':').collect();
1339 let attribute = if fields.len() == 2 {
1340 Attribute {
1341 key: fields[0].to_owned(),
1342 value: Some(fields[1].to_owned()),
1343 }
1344 } else {
1345 Attribute {
1346 key: fields[0].to_owned(),
1347 value: None,
1348 }
1349 };
1350
1351 if let Some(latest_media_desc) = lexer.desc.media_descriptions.last_mut() {
1352 latest_media_desc.attributes.push(attribute);
1353 Ok(Some(StateFn { f: s14 }))
1354 } else {
1355 Err(Error::SdpEmptyTimeDescription)
1356 }
1357}
1358
1359fn parse_time_units(value: &str) -> Result<i64> {
1360 let val = value.as_bytes();
1363 let len = val.len();
1364 let (num, factor) = match val.last() {
1365 Some(b'd') => (&value[..len - 1], 86400), Some(b'h') => (&value[..len - 1], 3600), Some(b'm') => (&value[..len - 1], 60), Some(b's') => (&value[..len - 1], 1), _ => (value, 1),
1370 };
1371 num.parse::<i64>()?
1372 .checked_mul(factor)
1373 .ok_or_else(|| Error::SdpInvalidValue(value.to_owned()))
1374}