diff options
Diffstat (limited to 'sdp/src/lib.rs')
-rw-r--r-- | sdp/src/lib.rs | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/sdp/src/lib.rs b/sdp/src/lib.rs new file mode 100644 index 0000000..68c3c70 --- /dev/null +++ b/sdp/src/lib.rs @@ -0,0 +1,128 @@ +use anyhow::{anyhow, bail}; +use std::str::FromStr; + +pub struct SessionDescription { + pub version: String, + pub originator: String, + pub session_name: String, + pub session_information: Option<String>, + pub description_uri: Option<String>, + pub email_address: Option<String>, + pub phone_number: Option<String>, + pub connection_information: Option<String>, + pub bandwidth: Vec<String>, + pub time_descriptions: Vec<TimeDescription>, + pub time_zone_adjustments: Option<String>, + pub encryption_key: Option<String>, + pub attributes: Vec<String>, + pub media_descriptions: Vec<MediaDescription>, +} + +pub struct TimeDescription { + pub time: String, + pub repeat_times: Vec<String>, +} + +pub struct MediaDescription { + pub name: String, + pub title: Option<String>, + pub connection_information: Option<String>, + pub bandwidth: Vec<String>, + pub encryption_key: Option<String>, + pub attributes: Vec<String>, +} + +impl FromStr for SessionDescription { + type Err = anyhow::Error; + fn from_str(s: &str) -> Result<Self, Self::Err> { + let mut version = None; + let mut originator = None; + let mut session_name = None; + let mut session_information = None; + let mut description_uri = None; + let mut email_address = None; + let mut phone_number = None; + let mut connection_information = None; + let mut encryption_key = None; + let mut time_zone_adjustments = None; + let mut bandwidth = Vec::new(); + let mut time_descriptions = Vec::new(); + let mut media_descriptions = Vec::new(); + let mut attributes = Vec::new(); + for line in s.lines() { + let (r#type, value) = line.split_once("=").ok_or(anyhow!("sdp line invalid"))?; + match r#type { + "v" => version = Some(value.to_string()), + "o" => originator = Some(value.to_string()), + "s" => session_name = Some(value.to_string()), + "i" => session_information = Some(value.to_string()), + "u" => description_uri = Some(value.to_string()), + "e" => email_address = Some(value.to_string()), + "p" => phone_number = Some(value.to_string()), + "t" => time_descriptions.push(TimeDescription { + repeat_times: Vec::new(), + time: value.to_string(), + }), + "r" => time_descriptions + .last_mut() + .ok_or(anyhow!("no time desc"))? + .repeat_times + .push(value.to_string()), + "z" => time_zone_adjustments = Some(value.to_string()), + "m" => media_descriptions.push(MediaDescription { + connection_information: None, + name: value.to_string(), + title: None, + encryption_key: None, + attributes: Vec::new(), + bandwidth: Vec::new(), + }), + "a" => { + if let Some(media_desc) = media_descriptions.last_mut() { + media_desc.attributes.push(value.to_string()) + } else { + attributes.push(value.to_string()) + } + } + "b" => { + if let Some(media_desc) = media_descriptions.last_mut() { + media_desc.bandwidth.push(value.to_string()) + } else { + bandwidth.push(value.to_string()) + } + } + "k" => { + if let Some(key) = media_descriptions.last_mut() { + key.encryption_key = Some(value.to_string()) + } else { + encryption_key = Some(value.to_string()) + } + } + "c" => { + if let Some(media_desc) = media_descriptions.last_mut() { + media_desc.connection_information = Some(value.to_string()) + } else { + connection_information = Some(value.to_string()) + } + } + x => bail!("unknown sdp type ({x:?})"), + } + } + Ok(Self { + bandwidth, + connection_information, + attributes, + description_uri, + email_address, + encryption_key, + phone_number, + session_information, + time_zone_adjustments, + media_descriptions, + originator: originator.ok_or(anyhow!("originator missing"))?, + session_name: session_name.ok_or(anyhow!("session name missing"))?, + version: version.ok_or(anyhow!("version missing"))?, + time_descriptions, + }) + } +} |