Skip to main content

rtc_sdp/description/
common.rs

1//! Fields shared by session and media descriptions.
2//!
3//! `c=` connection data ([`ConnectionInformation`](crate::description::common::ConnectionInformation), [`Address`](crate::description::common::Address)), `b=` bandwidth
4//! ([`Bandwidth`](crate::description::common::Bandwidth)) and `a=` attributes ([`Attribute`](crate::description::common::Attribute)) may appear at either level in SDP, with
5//! the media-level value overriding the session-level one — so they are modelled once here.
6//!
7//! An [`Attribute`](crate::description::common::Attribute) with no value is a flag, which is how `a=rtcp-mux` and the direction
8//! attributes are expressed.
9use std::fmt;
10
11use super::session::ATTR_KEY_CANDIDATE;
12
13/// Information describes the "i=" field which provides textual information
14/// about the session.
15pub type Information = String;
16
17/// ConnectionInformation defines the representation for the "c=" field
18/// containing connection data.
19#[derive(Debug, Default, Clone)]
20pub struct ConnectionInformation {
21    /// The network type, always `IN` (Internet) in practice.
22    pub network_type: String,
23    /// The address type, `IP4` or `IP6`.
24    pub address_type: String,
25    /// The connection address, absent for a bare `c=` line.
26    pub address: Option<Address>,
27}
28
29impl fmt::Display for ConnectionInformation {
30    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31        if let Some(address) = &self.address {
32            write!(f, "{} {} {}", self.network_type, self.address_type, address,)
33        } else {
34            write!(f, "{} {}", self.network_type, self.address_type,)
35        }
36    }
37}
38
39/// Address describes a structured address token from within the "c=" field.
40#[derive(Debug, Default, Clone)]
41pub struct Address {
42    /// The address itself: a host name, IPv4/IPv6 literal, or multicast group.
43    pub address: String,
44    /// The multicast TTL, for multicast addresses.
45    pub ttl: Option<isize>,
46    /// The number of consecutive multicast addresses in the range.
47    pub range: Option<isize>,
48}
49
50impl fmt::Display for Address {
51    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
52        write!(f, "{}", self.address)?;
53        if let Some(t) = &self.ttl {
54            write!(f, "/{t}")?;
55        }
56        if let Some(r) = &self.range {
57            write!(f, "/{r}")?;
58        }
59        Ok(())
60    }
61}
62
63/// Bandwidth describes an optional field which denotes the proposed bandwidth
64/// to be used by the session or media.
65#[derive(Debug, Default, Clone)]
66pub struct Bandwidth {
67    /// Whether the bandwidth type is experimental, written with an `X-` prefix.
68    pub experimental: bool,
69    /// The bandwidth modifier, such as `AS` (application-specific) or `CT` (conference total).
70    pub bandwidth_type: String,
71    /// The proposed bandwidth in kilobits per second.
72    pub bandwidth: u64,
73}
74
75impl fmt::Display for Bandwidth {
76    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
77        let output = if self.experimental { "X-" } else { "" };
78        write!(f, "{}{}:{}", output, self.bandwidth_type, self.bandwidth)
79    }
80}
81
82/// EncryptionKey describes the "k=" which conveys encryption key information.
83pub type EncryptionKey = String;
84
85/// Attribute describes the "a=" field which represents the primary means for
86/// extending SDP.
87#[derive(Debug, Default, Clone)]
88pub struct Attribute {
89    /// The attribute name, the part before the `:`.
90    pub key: String,
91    /// The attribute value, or `None` for a flag attribute such as `a=rtcp-mux`.
92    pub value: Option<String>,
93}
94
95impl fmt::Display for Attribute {
96    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
97        if let Some(value) = &self.value {
98            write!(f, "{}:{}", self.key, value)
99        } else {
100            write!(f, "{}", self.key)
101        }
102    }
103}
104
105impl Attribute {
106    /// new constructs a new attribute
107    pub fn new(key: String, value: Option<String>) -> Self {
108        Attribute { key, value }
109    }
110
111    /// is_ice_candidate returns true if the attribute key equals "candidate".
112    pub fn is_ice_candidate(&self) -> bool {
113        self.key.as_str() == ATTR_KEY_CANDIDATE
114    }
115}