1use std::collections::HashMap;
13use std::convert::TryFrom;
14use std::time::{Duration, SystemTime, UNIX_EPOCH};
15use std::{fmt, io};
16
17use url::Url;
18
19use crate::lexer::*;
20use crate::util::*;
21use shared::error::{Error, Result};
22
23use super::common::*;
24use super::media::*;
25
26pub const ATTR_KEY_CANDIDATE: &str = "candidate";
28pub const ATTR_KEY_END_OF_CANDIDATES: &str = "end-of-candidates";
30pub const ATTR_KEY_IDENTITY: &str = "identity";
32pub const ATTR_KEY_GROUP: &str = "group";
34pub const ATTR_KEY_SSRC: &str = "ssrc";
36pub const ATTR_KEY_SSRC_GROUP: &str = "ssrc-group";
38pub const ATTR_KEY_MSID: &str = "msid";
40pub const ATTR_KEY_MSID_SEMANTIC: &str = "msid-semantic";
42pub const ATTR_KEY_CONNECTION_SETUP: &str = "setup";
44pub const ATTR_KEY_MID: &str = "mid";
46pub const ATTR_KEY_ICELITE: &str = "ice-lite";
48pub const ATTR_KEY_RTCPMUX: &str = "rtcp-mux";
50pub const ATTR_KEY_RTCPRSIZE: &str = "rtcp-rsize";
52pub const ATTR_KEY_INACTIVE: &str = "inactive";
54pub const ATTR_KEY_RECV_ONLY: &str = "recvonly";
56pub const ATTR_KEY_SEND_ONLY: &str = "sendonly";
58pub const ATTR_KEY_SEND_RECV: &str = "sendrecv";
60pub const ATTR_KEY_EXT_MAP: &str = "extmap";
62pub const ATTR_KEY_EXTMAP_ALLOW_MIXED: &str = "extmap-allow-mixed";
64pub const ATTR_KEY_MAX_MESSAGE_SIZE: &str = "max-message-size";
66
67pub const SEMANTIC_TOKEN_LIP_SYNCHRONIZATION: &str = "LS";
69pub const SEMANTIC_TOKEN_FLOW_IDENTIFICATION: &str = "FID";
71pub const SEMANTIC_TOKEN_FORWARD_ERROR_CORRECTION: &str = "FEC";
73pub const SEMANTIC_TOKEN_FORWARD_ERROR_CORRECTION_FRAMEWORK: &str = "FEC-FR";
76pub const SEMANTIC_TOKEN_WEBRTC_MEDIA_STREAMS: &str = "WMS";
78
79pub type Version = isize;
82
83#[derive(Debug, Default, Clone)]
86pub struct Origin {
87 pub username: String,
89 pub session_id: u64,
91 pub session_version: u64,
93 pub network_type: String,
95 pub address_type: String,
97 pub unicast_address: String,
99}
100
101impl fmt::Display for Origin {
102 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
103 write!(
104 f,
105 "{} {} {} {} {} {}",
106 self.username,
107 self.session_id,
108 self.session_version,
109 self.network_type,
110 self.address_type,
111 self.unicast_address,
112 )
113 }
114}
115
116impl Origin {
117 pub fn new() -> Self {
119 Origin {
120 username: "".to_owned(),
121 session_id: 0,
122 session_version: 0,
123 network_type: "".to_owned(),
124 address_type: "".to_owned(),
125 unicast_address: "".to_owned(),
126 }
127 }
128}
129
130pub type SessionName = String;
133
134pub type EmailAddress = String;
138
139pub type PhoneNumber = String;
143
144#[derive(Debug, Default, Clone)]
147pub struct TimeZone {
148 pub adjustment_time: u64,
150 pub offset: i64,
152}
153
154impl fmt::Display for TimeZone {
155 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
156 write!(f, "{} {}", self.adjustment_time, self.offset)
157 }
158}
159
160#[derive(Debug, Default, Clone)]
164pub struct TimeDescription {
165 pub timing: Timing,
169
170 pub repeat_times: Vec<RepeatTime>,
174}
175
176#[derive(Debug, Default, Clone)]
179pub struct Timing {
180 pub start_time: u64,
182 pub stop_time: u64,
184}
185
186impl fmt::Display for Timing {
187 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
188 write!(f, "{} {}", self.start_time, self.stop_time)
189 }
190}
191
192#[derive(Debug, Default, Clone)]
195pub struct RepeatTime {
196 pub interval: i64,
198 pub duration: i64,
200 pub offsets: Vec<i64>,
202}
203
204impl fmt::Display for RepeatTime {
205 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
206 write!(f, "{} {}", self.interval, self.duration)?;
207
208 for value in &self.offsets {
209 write!(f, " {value}")?;
210 }
211 Ok(())
212 }
213}
214
215#[derive(Debug, Default, Clone)]
218pub struct SessionDescription {
219 pub version: Version,
223
224 pub origin: Origin,
228
229 pub session_name: SessionName,
233
234 pub session_information: Option<Information>,
238
239 pub uri: Option<Url>,
243
244 pub email_address: Option<EmailAddress>,
248
249 pub phone_number: Option<PhoneNumber>,
253
254 pub connection_information: Option<ConnectionInformation>,
258
259 pub bandwidth: Vec<Bandwidth>,
263
264 pub time_descriptions: Vec<TimeDescription>,
267
268 pub time_zones: Vec<TimeZone>,
272
273 pub encryption_key: Option<EncryptionKey>,
279
280 pub attributes: Vec<Attribute>,
286
287 pub media_descriptions: Vec<MediaDescription>,
289}
290
291impl fmt::Display for SessionDescription {
292 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
293 write_key_value(f, "v=", Some(&self.version))?;
294 write_key_value(f, "o=", Some(&self.origin))?;
295 write_key_value(f, "s=", Some(&self.session_name))?;
296
297 write_key_value(f, "i=", self.session_information.as_ref())?;
298
299 if let Some(uri) = &self.uri {
300 write_key_value(f, "u=", Some(uri))?;
301 }
302 write_key_value(f, "e=", self.email_address.as_ref())?;
303 write_key_value(f, "p=", self.phone_number.as_ref())?;
304 if let Some(connection_information) = &self.connection_information {
305 write_key_value(f, "c=", Some(&connection_information))?;
306 }
307
308 for bandwidth in &self.bandwidth {
309 write_key_value(f, "b=", Some(&bandwidth))?;
310 }
311 for time_description in &self.time_descriptions {
312 write_key_value(f, "t=", Some(&time_description.timing))?;
313 for repeat_time in &time_description.repeat_times {
314 write_key_value(f, "r=", Some(&repeat_time))?;
315 }
316 }
317
318 write_key_slice_of_values(f, "z=", &self.time_zones)?;
319
320 write_key_value(f, "k=", self.encryption_key.as_ref())?;
321 for attribute in &self.attributes {
322 write_key_value(f, "a=", Some(&attribute))?;
323 }
324
325 for media_description in &self.media_descriptions {
326 write_key_value(f, "m=", Some(&media_description.media_name))?;
327 write_key_value(f, "i=", media_description.media_title.as_ref())?;
328 if let Some(connection_information) = &media_description.connection_information {
329 write_key_value(f, "c=", Some(&connection_information))?;
330 }
331 for bandwidth in &media_description.bandwidth {
332 write_key_value(f, "b=", Some(&bandwidth))?;
333 }
334 write_key_value(f, "k=", media_description.encryption_key.as_ref())?;
335 for attribute in &media_description.attributes {
336 write_key_value(f, "a=", Some(&attribute))?;
337 }
338 }
339
340 Ok(())
341 }
342}
343
344impl SessionDescription {
346 pub fn new_jsep_session_description(identity: bool) -> Self {
351 let d = SessionDescription {
352 version: 0,
353 origin: Origin {
354 username: "-".to_string(),
355 session_id: new_session_id(),
356 session_version: SystemTime::now()
357 .duration_since(UNIX_EPOCH)
358 .unwrap_or_else(|_| Duration::from_secs(0))
359 .subsec_nanos() as u64,
360 network_type: "IN".to_string(),
361 address_type: "IP4".to_string(),
362 unicast_address: "0.0.0.0".to_string(),
363 },
364 session_name: "-".to_string(),
365 session_information: None,
366 uri: None,
367 email_address: None,
368 phone_number: None,
369 connection_information: None,
370 bandwidth: vec![],
371 time_descriptions: vec![TimeDescription {
372 timing: Timing {
373 start_time: 0,
374 stop_time: 0,
375 },
376 repeat_times: vec![],
377 }],
378 time_zones: vec![],
379 encryption_key: None,
380 attributes: vec![], media_descriptions: vec![],
382 };
383
384 if identity {
385 d.with_property_attribute(ATTR_KEY_IDENTITY.to_string())
386 } else {
387 d
388 }
389 }
390
391 pub fn with_property_attribute(mut self, key: String) -> Self {
393 self.attributes.push(Attribute::new(key, None));
394 self
395 }
396
397 pub fn with_value_attribute(mut self, key: String, value: String) -> Self {
399 self.attributes.push(Attribute::new(key, Some(value)));
400 self
401 }
402
403 pub fn with_fingerprint(self, algorithm: String, value: String) -> Self {
405 self.with_value_attribute("fingerprint".to_string(), algorithm + " " + value.as_str())
406 }
407
408 pub fn with_media(mut self, md: MediaDescription) -> Self {
410 self.media_descriptions.push(md);
411 self
412 }
413
414 fn build_codec_map(&self) -> HashMap<u8, Codec> {
415 let mut codecs: HashMap<u8, Codec> = HashMap::new();
416
417 for m in &self.media_descriptions {
418 codecs.extend(m.codecs());
419 }
420
421 codecs
422 }
423
424 pub fn get_codec_for_payload_type(&self, payload_type: u8) -> Result<Codec> {
426 let codecs = self.build_codec_map();
427
428 if let Some(codec) = codecs.get(&payload_type) {
429 Ok(codec.clone())
430 } else {
431 Err(Error::PayloadTypeNotFound)
432 }
433 }
434
435 pub fn get_payload_type_for_codec(&self, wanted: &Codec) -> Result<u8> {
438 let codecs = self.build_codec_map();
439
440 for (payload_type, codec) in codecs.iter() {
441 if codecs_match(wanted, codec) {
442 return Ok(*payload_type);
443 }
444 }
445
446 Err(Error::CodecNotFound)
447 }
448
449 pub fn has_attribute(&self, key: &str) -> bool {
451 self.attributes.iter().any(|a| a.key == key)
452 }
453
454 pub fn attribute(&self, key: &str) -> Option<&String> {
456 for a in &self.attributes {
457 if a.key == key {
458 return a.value.as_ref();
459 }
460 }
461 None
462 }
463
464 pub fn marshal(&self) -> String {
498 self.to_string()
499 }
500
501 pub fn unmarshal<R: io::BufRead + io::Seek>(reader: &mut R) -> Result<Self> {
580 let mut lexer = Lexer {
581 desc: SessionDescription {
582 version: 0,
583 origin: Origin::new(),
584 session_name: "".to_owned(),
585 session_information: None,
586 uri: None,
587 email_address: None,
588 phone_number: None,
589 connection_information: None,
590 bandwidth: vec![],
591 time_descriptions: vec![],
592 time_zones: vec![],
593 encryption_key: None,
594 attributes: vec![],
595 media_descriptions: vec![],
596 },
597 reader,
598 };
599
600 let mut state = Some(StateFn { f: s1 });
601 while let Some(s) = state {
602 state = (s.f)(&mut lexer)?;
603 }
604
605 Ok(lexer.desc)
606 }
607}
608
609impl From<SessionDescription> for String {
610 fn from(sdp: SessionDescription) -> String {
611 sdp.marshal()
612 }
613}
614
615impl TryFrom<String> for SessionDescription {
616 type Error = Error;
617 fn try_from(sdp_string: String) -> Result<Self> {
618 let mut reader = io::Cursor::new(sdp_string.as_bytes());
619 let session_description = SessionDescription::unmarshal(&mut reader)?;
620 Ok(session_description)
621 }
622}
623
624fn s1<'a, R: io::BufRead + io::Seek>(lexer: &mut Lexer<'a, R>) -> Result<Option<StateFn<'a, R>>> {
625 let (key, _) = read_type(lexer.reader)?;
626 if &key == b"v=" {
627 return Ok(Some(StateFn {
628 f: unmarshal_protocol_version,
629 }));
630 }
631
632 Err(Error::SdpInvalidSyntax(String::from_utf8(key)?))
633}
634
635fn s2<'a, R: io::BufRead + io::Seek>(lexer: &mut Lexer<'a, R>) -> Result<Option<StateFn<'a, R>>> {
636 let (key, _) = read_type(lexer.reader)?;
637 if &key == b"o=" {
638 return Ok(Some(StateFn {
639 f: unmarshal_origin,
640 }));
641 }
642
643 Err(Error::SdpInvalidSyntax(String::from_utf8(key)?))
644}
645
646fn s3<'a, R: io::BufRead + io::Seek>(lexer: &mut Lexer<'a, R>) -> Result<Option<StateFn<'a, R>>> {
647 let (key, _) = read_type(lexer.reader)?;
648 if &key == b"s=" {
649 return Ok(Some(StateFn {
650 f: unmarshal_session_name,
651 }));
652 }
653
654 Err(Error::SdpInvalidSyntax(String::from_utf8(key)?))
655}
656
657fn s4<'a, R: io::BufRead + io::Seek>(lexer: &mut Lexer<'a, R>) -> Result<Option<StateFn<'a, R>>> {
658 let (key, _) = read_type(lexer.reader)?;
659 match key.as_slice() {
660 b"i=" => Ok(Some(StateFn {
661 f: unmarshal_session_information,
662 })),
663 b"u=" => Ok(Some(StateFn { f: unmarshal_uri })),
664 b"e=" => Ok(Some(StateFn { f: unmarshal_email })),
665 b"p=" => Ok(Some(StateFn { f: unmarshal_phone })),
666 b"c=" => Ok(Some(StateFn {
667 f: unmarshal_session_connection_information,
668 })),
669 b"b=" => Ok(Some(StateFn {
670 f: unmarshal_session_bandwidth,
671 })),
672 b"t=" => Ok(Some(StateFn {
673 f: unmarshal_timing,
674 })),
675 _ => Err(Error::SdpInvalidSyntax(String::from_utf8(key)?)),
676 }
677}
678
679fn s5<'a, R: io::BufRead + io::Seek>(lexer: &mut Lexer<'a, R>) -> Result<Option<StateFn<'a, R>>> {
680 let (key, _) = read_type(lexer.reader)?;
681 match key.as_slice() {
682 b"b=" => Ok(Some(StateFn {
683 f: unmarshal_session_bandwidth,
684 })),
685 b"t=" => Ok(Some(StateFn {
686 f: unmarshal_timing,
687 })),
688 _ => Err(Error::SdpInvalidSyntax(String::from_utf8(key)?)),
689 }
690}
691
692fn s6<'a, R: io::BufRead + io::Seek>(lexer: &mut Lexer<'a, R>) -> Result<Option<StateFn<'a, R>>> {
693 let (key, _) = read_type(lexer.reader)?;
694 match key.as_slice() {
695 b"p=" => Ok(Some(StateFn { f: unmarshal_phone })),
696 b"c=" => Ok(Some(StateFn {
697 f: unmarshal_session_connection_information,
698 })),
699 b"b=" => Ok(Some(StateFn {
700 f: unmarshal_session_bandwidth,
701 })),
702 b"t=" => Ok(Some(StateFn {
703 f: unmarshal_timing,
704 })),
705 _ => Err(Error::SdpInvalidSyntax(String::from_utf8(key)?)),
706 }
707}
708
709fn s7<'a, R: io::BufRead + io::Seek>(lexer: &mut Lexer<'a, R>) -> Result<Option<StateFn<'a, R>>> {
710 let (key, _) = read_type(lexer.reader)?;
711 match key.as_slice() {
712 b"u=" => Ok(Some(StateFn { f: unmarshal_uri })),
713 b"e=" => Ok(Some(StateFn { f: unmarshal_email })),
714 b"p=" => Ok(Some(StateFn { f: unmarshal_phone })),
715 b"c=" => Ok(Some(StateFn {
716 f: unmarshal_session_connection_information,
717 })),
718 b"b=" => Ok(Some(StateFn {
719 f: unmarshal_session_bandwidth,
720 })),
721 b"t=" => Ok(Some(StateFn {
722 f: unmarshal_timing,
723 })),
724 _ => Err(Error::SdpInvalidSyntax(String::from_utf8(key)?)),
725 }
726}
727
728fn s8<'a, R: io::BufRead + io::Seek>(lexer: &mut Lexer<'a, R>) -> Result<Option<StateFn<'a, R>>> {
729 let (key, _) = read_type(lexer.reader)?;
730 match key.as_slice() {
731 b"c=" => Ok(Some(StateFn {
732 f: unmarshal_session_connection_information,
733 })),
734 b"b=" => Ok(Some(StateFn {
735 f: unmarshal_session_bandwidth,
736 })),
737 b"t=" => Ok(Some(StateFn {
738 f: unmarshal_timing,
739 })),
740 _ => Err(Error::SdpInvalidSyntax(String::from_utf8(key)?)),
741 }
742}
743
744fn s9<'a, R: io::BufRead + io::Seek>(lexer: &mut Lexer<'a, R>) -> Result<Option<StateFn<'a, R>>> {
745 let (key, num_bytes) = read_type(lexer.reader)?;
746 if key.is_empty() && num_bytes == 0 {
747 return Ok(None);
748 }
749
750 match key.as_slice() {
751 b"z=" => Ok(Some(StateFn {
752 f: unmarshal_time_zones,
753 })),
754 b"k=" => Ok(Some(StateFn {
755 f: unmarshal_session_encryption_key,
756 })),
757 b"a=" => Ok(Some(StateFn {
758 f: unmarshal_session_attribute,
759 })),
760 b"r=" => Ok(Some(StateFn {
761 f: unmarshal_repeat_times,
762 })),
763 b"t=" => Ok(Some(StateFn {
764 f: unmarshal_timing,
765 })),
766 b"m=" => Ok(Some(StateFn {
767 f: unmarshal_media_description,
768 })),
769 _ => Err(Error::SdpInvalidSyntax(String::from_utf8(key)?)),
770 }
771}
772
773fn s10<'a, R: io::BufRead + io::Seek>(lexer: &mut Lexer<'a, R>) -> Result<Option<StateFn<'a, R>>> {
774 let (key, _) = read_type(lexer.reader)?;
775 match key.as_slice() {
776 b"e=" => Ok(Some(StateFn { f: unmarshal_email })),
777 b"p=" => Ok(Some(StateFn { f: unmarshal_phone })),
778 b"c=" => Ok(Some(StateFn {
779 f: unmarshal_session_connection_information,
780 })),
781 b"b=" => Ok(Some(StateFn {
782 f: unmarshal_session_bandwidth,
783 })),
784 b"t=" => Ok(Some(StateFn {
785 f: unmarshal_timing,
786 })),
787 _ => Err(Error::SdpInvalidSyntax(String::from_utf8(key)?)),
788 }
789}
790
791fn s11<'a, R: io::BufRead + io::Seek>(lexer: &mut Lexer<'a, R>) -> Result<Option<StateFn<'a, R>>> {
792 let (key, num_bytes) = read_type(lexer.reader)?;
793 if key.is_empty() && num_bytes == 0 {
794 return Ok(None);
795 }
796
797 match key.as_slice() {
798 b"a=" => Ok(Some(StateFn {
799 f: unmarshal_session_attribute,
800 })),
801 b"m=" => Ok(Some(StateFn {
802 f: unmarshal_media_description,
803 })),
804 _ => Err(Error::SdpInvalidSyntax(String::from_utf8(key)?)),
805 }
806}
807
808fn s12<'a, R: io::BufRead + io::Seek>(lexer: &mut Lexer<'a, R>) -> Result<Option<StateFn<'a, R>>> {
809 let (key, num_bytes) = read_type(lexer.reader)?;
810 if key.is_empty() && num_bytes == 0 {
811 return Ok(None);
812 }
813
814 match key.as_slice() {
815 b"a=" => Ok(Some(StateFn {
816 f: unmarshal_media_attribute,
817 })),
818 b"k=" => Ok(Some(StateFn {
819 f: unmarshal_media_encryption_key,
820 })),
821 b"b=" => Ok(Some(StateFn {
822 f: unmarshal_media_bandwidth,
823 })),
824 b"c=" => Ok(Some(StateFn {
825 f: unmarshal_media_connection_information,
826 })),
827 b"i=" => Ok(Some(StateFn {
828 f: unmarshal_media_title,
829 })),
830 b"m=" => Ok(Some(StateFn {
831 f: unmarshal_media_description,
832 })),
833 _ => Err(Error::SdpInvalidSyntax(String::from_utf8(key)?)),
834 }
835}
836
837fn s13<'a, R: io::BufRead + io::Seek>(lexer: &mut Lexer<'a, R>) -> Result<Option<StateFn<'a, R>>> {
838 let (key, num_bytes) = read_type(lexer.reader)?;
839 if key.is_empty() && num_bytes == 0 {
840 return Ok(None);
841 }
842
843 match key.as_slice() {
844 b"a=" => Ok(Some(StateFn {
845 f: unmarshal_session_attribute,
846 })),
847 b"k=" => Ok(Some(StateFn {
848 f: unmarshal_session_encryption_key,
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 s14<'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 {
869 f: unmarshal_media_encryption_key,
870 })),
871 b"b=" => Ok(Some(StateFn {
873 f: unmarshal_media_bandwidth,
874 })),
875 b"c=" => Ok(Some(StateFn {
877 f: unmarshal_media_connection_information,
878 })),
879 b"i=" => Ok(Some(StateFn {
881 f: unmarshal_media_title,
882 })),
883 b"m=" => Ok(Some(StateFn {
884 f: unmarshal_media_description,
885 })),
886 _ => Err(Error::SdpInvalidSyntax(String::from_utf8(key)?)),
887 }
888}
889
890fn s15<'a, R: io::BufRead + io::Seek>(lexer: &mut Lexer<'a, R>) -> Result<Option<StateFn<'a, R>>> {
891 let (key, num_bytes) = read_type(lexer.reader)?;
892 if key.is_empty() && num_bytes == 0 {
893 return Ok(None);
894 }
895
896 match key.as_slice() {
897 b"a=" => Ok(Some(StateFn {
898 f: unmarshal_media_attribute,
899 })),
900 b"k=" => Ok(Some(StateFn {
901 f: unmarshal_media_encryption_key,
902 })),
903 b"b=" => Ok(Some(StateFn {
904 f: unmarshal_media_bandwidth,
905 })),
906 b"c=" => Ok(Some(StateFn {
907 f: unmarshal_media_connection_information,
908 })),
909 b"i=" => Ok(Some(StateFn {
911 f: unmarshal_media_title,
912 })),
913 b"m=" => Ok(Some(StateFn {
914 f: unmarshal_media_description,
915 })),
916 _ => Err(Error::SdpInvalidSyntax(String::from_utf8(key)?)),
917 }
918}
919
920fn s16<'a, R: io::BufRead + io::Seek>(lexer: &mut Lexer<'a, R>) -> Result<Option<StateFn<'a, R>>> {
921 let (key, num_bytes) = read_type(lexer.reader)?;
922 if key.is_empty() && num_bytes == 0 {
923 return Ok(None);
924 }
925
926 match key.as_slice() {
927 b"a=" => Ok(Some(StateFn {
928 f: unmarshal_media_attribute,
929 })),
930 b"k=" => Ok(Some(StateFn {
931 f: unmarshal_media_encryption_key,
932 })),
933 b"c=" => Ok(Some(StateFn {
934 f: unmarshal_media_connection_information,
935 })),
936 b"b=" => Ok(Some(StateFn {
937 f: unmarshal_media_bandwidth,
938 })),
939 b"i=" => Ok(Some(StateFn {
941 f: unmarshal_media_title,
942 })),
943 b"m=" => Ok(Some(StateFn {
944 f: unmarshal_media_description,
945 })),
946 _ => Err(Error::SdpInvalidSyntax(String::from_utf8(key)?)),
947 }
948}
949
950fn unmarshal_protocol_version<'a, R: io::BufRead + io::Seek>(
951 lexer: &mut Lexer<'a, R>,
952) -> Result<Option<StateFn<'a, R>>> {
953 let (value, _) = read_value(lexer.reader)?;
954
955 let version = value.parse::<u32>()?;
956
957 if version != 0 {
960 return Err(Error::SdpInvalidSyntax(value));
961 }
962
963 Ok(Some(StateFn { f: s2 }))
964}
965
966fn unmarshal_origin<'a, R: io::BufRead + io::Seek>(
967 lexer: &mut Lexer<'a, R>,
968) -> Result<Option<StateFn<'a, R>>> {
969 let (value, _) = read_value(lexer.reader)?;
970
971 let fields: Vec<&str> = value.split_whitespace().collect();
972 if fields.len() != 6 {
973 return Err(Error::SdpInvalidSyntax(format!("`o={value}`")));
974 }
975
976 let session_id = fields[1].parse::<u64>()?;
977 let session_version = fields[2].parse::<u64>()?;
978
979 let i = index_of(fields[3], &["IN"]);
982 if i == -1 {
983 return Err(Error::SdpInvalidValue(fields[3].to_owned()));
984 }
985
986 let i = index_of(fields[4], &["IP4", "IP6"]);
989 if i == -1 {
990 return Err(Error::SdpInvalidValue(fields[4].to_owned()));
991 }
992
993 lexer.desc.origin = Origin {
996 username: fields[0].to_owned(),
997 session_id,
998 session_version,
999 network_type: fields[3].to_owned(),
1000 address_type: fields[4].to_owned(),
1001 unicast_address: fields[5].to_owned(),
1002 };
1003
1004 Ok(Some(StateFn { f: s3 }))
1005}
1006
1007fn unmarshal_session_name<'a, R: io::BufRead + io::Seek>(
1008 lexer: &mut Lexer<'a, R>,
1009) -> Result<Option<StateFn<'a, R>>> {
1010 let (value, _) = read_value(lexer.reader)?;
1011 lexer.desc.session_name = value;
1012 Ok(Some(StateFn { f: s4 }))
1013}
1014
1015fn unmarshal_session_information<'a, R: io::BufRead + io::Seek>(
1016 lexer: &mut Lexer<'a, R>,
1017) -> Result<Option<StateFn<'a, R>>> {
1018 let (value, _) = read_value(lexer.reader)?;
1019 lexer.desc.session_information = Some(value);
1020 Ok(Some(StateFn { f: s7 }))
1021}
1022
1023fn unmarshal_uri<'a, R: io::BufRead + io::Seek>(
1024 lexer: &mut Lexer<'a, R>,
1025) -> Result<Option<StateFn<'a, R>>> {
1026 let (value, _) = read_value(lexer.reader)?;
1027 lexer.desc.uri = Some(Url::parse(&value)?);
1028 Ok(Some(StateFn { f: s10 }))
1029}
1030
1031fn unmarshal_email<'a, R: io::BufRead + io::Seek>(
1032 lexer: &mut Lexer<'a, R>,
1033) -> Result<Option<StateFn<'a, R>>> {
1034 let (value, _) = read_value(lexer.reader)?;
1035 lexer.desc.email_address = Some(value);
1036 Ok(Some(StateFn { f: s6 }))
1037}
1038
1039fn unmarshal_phone<'a, R: io::BufRead + io::Seek>(
1040 lexer: &mut Lexer<'a, R>,
1041) -> Result<Option<StateFn<'a, R>>> {
1042 let (value, _) = read_value(lexer.reader)?;
1043 lexer.desc.phone_number = Some(value);
1044 Ok(Some(StateFn { f: s8 }))
1045}
1046
1047fn unmarshal_session_connection_information<'a, R: io::BufRead + io::Seek>(
1048 lexer: &mut Lexer<'a, R>,
1049) -> Result<Option<StateFn<'a, R>>> {
1050 let (value, _) = read_value(lexer.reader)?;
1051 lexer.desc.connection_information = unmarshal_connection_information(&value)?;
1052 Ok(Some(StateFn { f: s5 }))
1053}
1054
1055fn unmarshal_connection_information(value: &str) -> Result<Option<ConnectionInformation>> {
1056 let fields: Vec<&str> = value.split_whitespace().collect();
1057 if fields.len() < 2 {
1058 return Err(Error::SdpInvalidSyntax(format!("`c={value}`")));
1059 }
1060
1061 let i = index_of(fields[0], &["IN"]);
1064 if i == -1 {
1065 return Err(Error::SdpInvalidValue(fields[0].to_owned()));
1066 }
1067
1068 let i = index_of(fields[1], &["IP4", "IP6"]);
1071 if i == -1 {
1072 return Err(Error::SdpInvalidValue(fields[1].to_owned()));
1073 }
1074
1075 let address = if fields.len() > 2 {
1076 Some(Address {
1077 address: fields[2].to_owned(),
1078 ttl: None,
1079 range: None,
1080 })
1081 } else {
1082 None
1083 };
1084
1085 Ok(Some(ConnectionInformation {
1086 network_type: fields[0].to_owned(),
1087 address_type: fields[1].to_owned(),
1088 address,
1089 }))
1090}
1091
1092fn unmarshal_session_bandwidth<'a, R: io::BufRead + io::Seek>(
1093 lexer: &mut Lexer<'a, R>,
1094) -> Result<Option<StateFn<'a, R>>> {
1095 let (value, _) = read_value(lexer.reader)?;
1096 lexer.desc.bandwidth.push(unmarshal_bandwidth(&value)?);
1097 Ok(Some(StateFn { f: s5 }))
1098}
1099
1100fn unmarshal_bandwidth(value: &str) -> Result<Bandwidth> {
1101 let mut parts: Vec<&str> = value.split(':').collect();
1102 if parts.len() != 2 {
1103 return Err(Error::SdpInvalidSyntax(format!("`b={value}`")));
1104 }
1105
1106 let experimental = parts[0].starts_with("X-");
1107 if experimental {
1108 parts[0] = parts[0].trim_start_matches("X-");
1109 }
1110 let bandwidth = parts[1].parse::<u64>()?;
1114
1115 Ok(Bandwidth {
1116 experimental,
1117 bandwidth_type: parts[0].to_owned(),
1118 bandwidth,
1119 })
1120}
1121
1122fn unmarshal_timing<'a, R: io::BufRead + io::Seek>(
1123 lexer: &mut Lexer<'a, R>,
1124) -> Result<Option<StateFn<'a, R>>> {
1125 let (value, _) = read_value(lexer.reader)?;
1126
1127 let fields: Vec<&str> = value.split_whitespace().collect();
1128 if fields.len() < 2 {
1129 return Err(Error::SdpInvalidSyntax(format!("`t={value}`")));
1130 }
1131
1132 let start_time = fields[0].parse::<u64>()?;
1133 let stop_time = fields[1].parse::<u64>()?;
1134
1135 lexer.desc.time_descriptions.push(TimeDescription {
1136 timing: Timing {
1137 start_time,
1138 stop_time,
1139 },
1140 repeat_times: vec![],
1141 });
1142
1143 Ok(Some(StateFn { f: s9 }))
1144}
1145
1146fn unmarshal_repeat_times<'a, R: io::BufRead + io::Seek>(
1147 lexer: &mut Lexer<'a, R>,
1148) -> Result<Option<StateFn<'a, R>>> {
1149 let (value, _) = read_value(lexer.reader)?;
1150
1151 let fields: Vec<&str> = value.split_whitespace().collect();
1152 if fields.len() < 3 {
1153 return Err(Error::SdpInvalidSyntax(format!("`r={value}`")));
1154 }
1155
1156 if let Some(latest_time_desc) = lexer.desc.time_descriptions.last_mut() {
1157 let interval = parse_time_units(fields[0])?;
1158 let duration = parse_time_units(fields[1])?;
1159 let mut offsets = vec![];
1160 for field in fields.iter().skip(2) {
1161 let offset = parse_time_units(field)?;
1162 offsets.push(offset);
1163 }
1164 latest_time_desc.repeat_times.push(RepeatTime {
1165 interval,
1166 duration,
1167 offsets,
1168 });
1169
1170 Ok(Some(StateFn { f: s9 }))
1171 } else {
1172 Err(Error::SdpEmptyTimeDescription)
1173 }
1174}
1175
1176fn unmarshal_time_zones<'a, R: io::BufRead + io::Seek>(
1177 lexer: &mut Lexer<'a, R>,
1178) -> Result<Option<StateFn<'a, R>>> {
1179 let (value, _) = read_value(lexer.reader)?;
1180
1181 let fields: Vec<&str> = value.split_whitespace().collect();
1185 if !fields.len().is_multiple_of(2) {
1186 return Err(Error::SdpInvalidSyntax(format!("`t={value}`")));
1187 }
1188
1189 for i in (0..fields.len()).step_by(2) {
1190 let adjustment_time = fields[i].parse::<u64>()?;
1191 let offset = parse_time_units(fields[i + 1])?;
1192
1193 lexer.desc.time_zones.push(TimeZone {
1194 adjustment_time,
1195 offset,
1196 });
1197 }
1198
1199 Ok(Some(StateFn { f: s13 }))
1200}
1201
1202fn unmarshal_session_encryption_key<'a, R: io::BufRead + io::Seek>(
1203 lexer: &mut Lexer<'a, R>,
1204) -> Result<Option<StateFn<'a, R>>> {
1205 let (value, _) = read_value(lexer.reader)?;
1206 lexer.desc.encryption_key = Some(value);
1207 Ok(Some(StateFn { f: s11 }))
1208}
1209
1210fn unmarshal_session_attribute<'a, R: io::BufRead + io::Seek>(
1211 lexer: &mut Lexer<'a, R>,
1212) -> Result<Option<StateFn<'a, R>>> {
1213 let (value, _) = read_value(lexer.reader)?;
1214
1215 let fields: Vec<&str> = value.splitn(2, ':').collect();
1216 let attribute = if fields.len() == 2 {
1217 Attribute {
1218 key: fields[0].to_owned(),
1219 value: Some(fields[1].to_owned()),
1220 }
1221 } else {
1222 Attribute {
1223 key: fields[0].to_owned(),
1224 value: None,
1225 }
1226 };
1227 lexer.desc.attributes.push(attribute);
1228
1229 Ok(Some(StateFn { f: s11 }))
1230}
1231
1232fn unmarshal_media_description<'a, R: io::BufRead + io::Seek>(
1233 lexer: &mut Lexer<'a, R>,
1234) -> Result<Option<StateFn<'a, R>>> {
1235 let (value, _) = read_value(lexer.reader)?;
1236
1237 let fields: Vec<&str> = value.split_whitespace().collect();
1238 if fields.len() < 4 {
1239 return Err(Error::SdpInvalidSyntax(format!("`m={value}`")));
1240 }
1241
1242 let i = index_of(
1248 fields[0],
1249 &["audio", "video", "text", "application", "message", "image"],
1250 );
1251 if i == -1 {
1252 return Err(Error::SdpInvalidValue(fields[0].to_owned()));
1253 }
1254
1255 let parts: Vec<&str> = fields[1].split('/').collect();
1257 let port_value = parts[0].parse::<u16>()? as isize;
1258 let port_range = if parts.len() > 1 {
1259 Some(parts[1].parse::<i32>()? as isize)
1260 } else {
1261 None
1262 };
1263
1264 let mut protos = vec![];
1273 for proto in fields[2].split('/').collect::<Vec<&str>>() {
1274 if proto.is_empty() {
1275 return Err(Error::SdpInvalidValue(fields[2].to_owned()));
1276 }
1277 protos.push(proto.to_owned());
1278 }
1279
1280 let mut formats = vec![];
1282 for field in fields.iter().skip(3) {
1283 formats.push(field.to_string());
1284 }
1285
1286 lexer.desc.media_descriptions.push(MediaDescription {
1287 media_name: MediaName {
1288 media: fields[0].to_owned(),
1289 port: RangedPort {
1290 value: port_value,
1291 range: port_range,
1292 },
1293 protos,
1294 formats,
1295 },
1296 media_title: None,
1297 connection_information: None,
1298 bandwidth: vec![],
1299 encryption_key: None,
1300 attributes: vec![],
1301 });
1302
1303 Ok(Some(StateFn { f: s12 }))
1304}
1305
1306fn unmarshal_media_title<'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 latest_media_desc.media_title = Some(value);
1313 Ok(Some(StateFn { f: s16 }))
1314 } else {
1315 Err(Error::SdpEmptyTimeDescription)
1316 }
1317}
1318
1319fn unmarshal_media_connection_information<'a, R: io::BufRead + io::Seek>(
1320 lexer: &mut Lexer<'a, R>,
1321) -> Result<Option<StateFn<'a, R>>> {
1322 let (value, _) = read_value(lexer.reader)?;
1323
1324 if let Some(latest_media_desc) = lexer.desc.media_descriptions.last_mut() {
1325 latest_media_desc.connection_information = unmarshal_connection_information(&value)?;
1326 Ok(Some(StateFn { f: s15 }))
1327 } else {
1328 Err(Error::SdpEmptyTimeDescription)
1329 }
1330}
1331
1332fn unmarshal_media_bandwidth<'a, R: io::BufRead + io::Seek>(
1333 lexer: &mut Lexer<'a, R>,
1334) -> Result<Option<StateFn<'a, R>>> {
1335 let (value, _) = read_value(lexer.reader)?;
1336
1337 if let Some(latest_media_desc) = lexer.desc.media_descriptions.last_mut() {
1338 let bandwidth = unmarshal_bandwidth(&value)?;
1339 latest_media_desc.bandwidth.push(bandwidth);
1340 Ok(Some(StateFn { f: s15 }))
1341 } else {
1342 Err(Error::SdpEmptyTimeDescription)
1343 }
1344}
1345
1346fn unmarshal_media_encryption_key<'a, R: io::BufRead + io::Seek>(
1347 lexer: &mut Lexer<'a, R>,
1348) -> Result<Option<StateFn<'a, R>>> {
1349 let (value, _) = read_value(lexer.reader)?;
1350
1351 if let Some(latest_media_desc) = lexer.desc.media_descriptions.last_mut() {
1352 latest_media_desc.encryption_key = Some(value);
1353 Ok(Some(StateFn { f: s14 }))
1354 } else {
1355 Err(Error::SdpEmptyTimeDescription)
1356 }
1357}
1358
1359fn unmarshal_media_attribute<'a, R: io::BufRead + io::Seek>(
1360 lexer: &mut Lexer<'a, R>,
1361) -> Result<Option<StateFn<'a, R>>> {
1362 let (value, _) = read_value(lexer.reader)?;
1363
1364 let fields: Vec<&str> = value.splitn(2, ':').collect();
1365 let attribute = if fields.len() == 2 {
1366 Attribute {
1367 key: fields[0].to_owned(),
1368 value: Some(fields[1].to_owned()),
1369 }
1370 } else {
1371 Attribute {
1372 key: fields[0].to_owned(),
1373 value: None,
1374 }
1375 };
1376
1377 if let Some(latest_media_desc) = lexer.desc.media_descriptions.last_mut() {
1378 latest_media_desc.attributes.push(attribute);
1379 Ok(Some(StateFn { f: s14 }))
1380 } else {
1381 Err(Error::SdpEmptyTimeDescription)
1382 }
1383}
1384
1385fn parse_time_units(value: &str) -> Result<i64> {
1386 let val = value.as_bytes();
1389 let len = val.len();
1390 let (num, factor) = match val.last() {
1391 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),
1396 };
1397 num.parse::<i64>()?
1398 .checked_mul(factor)
1399 .ok_or_else(|| Error::SdpInvalidValue(value.to_owned()))
1400}