1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
use std::borrow::Cow;

use derive_into_owned::IntoOwned;

use crate::{
    attributes::{
        candidate, dtls, extmap, ice::IceParameter, msid, rtcp, rtpmap, AttributeLine, BundleGroup,
        Control, Direction, Fingerprint, Fmtp, Ice, RtcpOption, Rtp, Ssrc, SsrcGroup,
    },
    lines::{connection::Connection, media::Media, SessionLine},
    SdpLine,
};

#[derive(Default, IntoOwned, PartialEq)]
#[cfg_attr(feature = "debug", derive(Debug))]
#[cfg_attr(
    feature = "serde",
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "camelCase")
)]
pub struct MediaSection<'a> {
    pub r#type: Cow<'a, str>,
    pub port: u32,
    pub protocol: Vec<Cow<'a, str>>,
    pub payloads: Vec<Cow<'a, str>>,

    pub connection: Option<Connection>,
    pub candidates: Vec<candidate::Candidate<'a>>,
    // pub ice: Vec<ice::IceParameter<'a>>,
    pub ice: Ice<'a>,
    pub mid: Option<Cow<'a, str>>,
    pub msid_semantic: Option<msid::MsidSemantic<'a>>,
    pub msid: Option<msid::Msid<'a>>,
    pub rtp_map: Vec<rtpmap::RtpMap<'a>>,
    pub p_time: Option<rtpmap::PTime>,
    pub ssrc: Vec<Ssrc<'a>>,
    pub bundle_group: Option<BundleGroup<'a>>,
    pub bundle_only: bool,
    pub ssrc_group: Option<SsrcGroup>,
    pub fingerprint: Option<Fingerprint<'a>>,
    pub direction: Option<Direction>,
    pub rtp: Option<Rtp<'a>>,
    pub rtcp: Option<rtcp::Rtcp>,
    pub fmtp: Vec<Fmtp<'a>>,
    pub rtcp_fb: Vec<rtcp::Fb<'a>>,
    pub rtcp_option: Vec<RtcpOption>,
    pub control: Option<Control<'a>>,
    pub setup_role: Option<dtls::SetupRole>,
    pub extmap: Vec<extmap::Extmap<'a>>,

    pub attributes: Vec<AttributeLine<'a>>,
}

impl<'a> MediaSection<'a> {
    pub fn media(&self) -> Media<'a> {
        Media {
            r#type: self.r#type.clone(),
            port: self.port,
            protocol: self.protocol.clone(),
            payloads: self.payloads.clone(),
        }
    }
    pub(crate) fn add_line(&mut self, line: SdpLine<'a>) {
        use AttributeLine::*;
        use SessionLine::*;
        match line {
            SdpLine::Session(Media(_)) => unreachable!(),
            SdpLine::Session(SessionLine::Connection(conn)) => self.connection = Some(conn),
            #[cfg(feature = "debug")]
            SdpLine::Session(session) => eprintln!("🔥 {:#?}", session),
            #[cfg(not(feature = "debug"))]
            SdpLine::Session(session) => eprintln!("🔥 {}", crate::ufmt_to_string(&session)),

            SdpLine::Attribute(Candidate(candidate)) => self.candidates.push(candidate),
            SdpLine::Attribute(Ice(IceParameter::Options(o))) => self.ice.options = Some(o),
            SdpLine::Attribute(Ice(IceParameter::Ufrag(o))) => self.ice.ufrag = Some(o),
            SdpLine::Attribute(Ice(IceParameter::Pwd(o))) => self.ice.pwd = Some(o),
            SdpLine::Attribute(attr @ Ice(_)) => self.attributes.push(attr),
            SdpLine::Attribute(Mid(mid)) => self.mid = Some(mid.0),
            SdpLine::Attribute(MsidSemantic(semantic)) => self.msid_semantic = Some(semantic),
            SdpLine::Attribute(Msid(msid)) => self.msid = Some(msid),
            SdpLine::Attribute(RtpMap(rtp_map)) => self.rtp_map.push(rtp_map),
            SdpLine::Attribute(PTime(p_time)) => self.p_time = Some(p_time),
            SdpLine::Attribute(Ssrc(ssrc)) => self.ssrc.push(ssrc),
            SdpLine::Attribute(BundleGroup(bundle_group)) => self.bundle_group = Some(bundle_group),
            SdpLine::Attribute(SsrcGroup(ssrc_group)) => self.ssrc_group = Some(ssrc_group),
            SdpLine::Attribute(Fingerprint(fingerprint)) => self.fingerprint = Some(fingerprint),
            SdpLine::Attribute(Direction(direction)) => self.direction = Some(direction),

            SdpLine::Attribute(Rtp(rtp)) => self.rtp = Some(rtp),
            SdpLine::Attribute(Rtcp(rtcp)) => self.rtcp = Some(rtcp),
            SdpLine::Attribute(Fmtp(fmtp)) => self.fmtp.push(fmtp),
            SdpLine::Attribute(RtcpFb(rtcp_fb)) => self.rtcp_fb.push(rtcp_fb),
            SdpLine::Attribute(RtcpOption(rtcp_option)) => self.rtcp_option.push(rtcp_option),
            SdpLine::Attribute(Control(control)) => self.control = Some(control),
            SdpLine::Attribute(SetupRole(setup_role)) => self.setup_role = Some(setup_role),
            SdpLine::Attribute(Extmap(extmap)) => self.extmap.push(extmap),
            SdpLine::Attribute(AttributeLine::BundleOnly) => self.bundle_only = true,
            SdpLine::Attribute(attr) => self.attributes.push(attr),
            SdpLine::Comment(_) => {}
        }
    }
}

impl<'a> From<Media<'a>> for MediaSection<'a> {
    fn from(mline: Media<'a>) -> Self {
        Self {
            r#type: mline.r#type,
            port: mline.port,
            protocol: mline.protocol,
            payloads: mline.payloads,
            ..Default::default()
        }
    }
}