Skip to content

Commit

Permalink
sdp: Negotiate extmap-allow-mixed (#604)
Browse files Browse the repository at this point in the history
This allows both one-byte and two-byte headers
  • Loading branch information
haaspors committed Aug 18, 2024
1 parent 88dff7b commit 23bbc1f
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 0 deletions.
5 changes: 5 additions & 0 deletions sdp/src/description/media.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@ pub struct MediaDescription {
}

impl MediaDescription {
/// Returns whether an attribute exists
pub fn has_attribute(&self, key: &str) -> bool {
self.attributes.iter().any(|a| a.key == key)
}

/// attribute returns the value of an attribute and if it exists
pub fn attribute(&self, key: &str) -> Option<Option<&str>> {
for a in &self.attributes {
Expand Down
6 changes: 6 additions & 0 deletions sdp/src/description/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ pub const ATTR_KEY_RECV_ONLY: &str = "recvonly";
pub const ATTR_KEY_SEND_ONLY: &str = "sendonly";
pub const ATTR_KEY_SEND_RECV: &str = "sendrecv";
pub const ATTR_KEY_EXT_MAP: &str = "extmap";
pub const ATTR_KEY_EXTMAP_ALLOW_MIXED: &str = "extmap-allow-mixed";

/// Constants for semantic tokens used in JSEP
pub const SEMANTIC_TOKEN_LIP_SYNCHRONIZATION: &str = "LS";
Expand Down Expand Up @@ -409,6 +410,11 @@ impl SessionDescription {
Err(Error::CodecNotFound)
}

/// Returns whether an attribute exists
pub fn has_attribute(&self, key: &str) -> bool {
self.attributes.iter().any(|a| a.key == key)
}

/// Attribute returns the value of an attribute and if it exists
pub fn attribute(&self, key: &str) -> Option<&String> {
for a in &self.attributes {
Expand Down
9 changes: 9 additions & 0 deletions webrtc/src/peer_connection/peer_connection_internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -771,6 +771,7 @@ impl PeerConnectionInternal {
let params = PopulateSdpParams {
media_description_fingerprint: self.setting_engine.sdp_media_level_fingerprints,
is_icelite: self.setting_engine.candidates.ice_lite,
extmap_allow_mixed: true,
connection_role: DEFAULT_DTLS_ROLE_OFFER.to_connection_role(),
ice_gathering_state: self.ice_gathering_state(),
match_bundle_group: None,
Expand Down Expand Up @@ -804,8 +805,12 @@ impl PeerConnectionInternal {
let remote_description = self.remote_description().await;
let mut media_sections = vec![];
let mut already_have_application_media_section = false;
let mut extmap_allow_mixed = false;

if let Some(remote_description) = remote_description.as_ref() {
if let Some(parsed) = &remote_description.parsed {
extmap_allow_mixed = parsed.has_attribute(ATTR_KEY_EXTMAP_ALLOW_MIXED);

for media in &parsed.media_descriptions {
if let Some(mid_value) = get_mid_value(media) {
if mid_value.is_empty() {
Expand All @@ -830,6 +835,8 @@ impl PeerConnectionInternal {
continue;
}

let extmap_allow_mixed = media.has_attribute(ATTR_KEY_EXTMAP_ALLOW_MIXED);

if let Some(t) = find_by_mid(mid_value, &mut local_transceivers).await {
t.sender().await.set_negotiated();
let media_transceivers = vec![t];
Expand All @@ -843,6 +850,7 @@ impl PeerConnectionInternal {
transceivers: media_transceivers,
rid_map: get_rids(media),
offered_direction: (!include_unmatched).then(|| direction),
extmap_allow_mixed,
..Default::default()
});
} else {
Expand Down Expand Up @@ -896,6 +904,7 @@ impl PeerConnectionInternal {
let params = PopulateSdpParams {
media_description_fingerprint: self.setting_engine.sdp_media_level_fingerprints,
is_icelite: self.setting_engine.candidates.ice_lite,
extmap_allow_mixed,
connection_role,
ice_gathering_state: self.ice_gathering_state(),
match_bundle_group,
Expand Down
11 changes: 11 additions & 0 deletions webrtc/src/peer_connection/sdp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,10 @@ pub(crate) async fn add_transceiver_sdp(
.with_property_attribute(ATTR_KEY_RTCPMUX.to_owned())
.with_property_attribute(ATTR_KEY_RTCPRSIZE.to_owned());

if media_section.extmap_allow_mixed {
media = media.with_property_attribute(ATTR_KEY_EXTMAP_ALLOW_MIXED.to_owned());
}

let codecs = t.get_codecs().await;
for codec in &codecs {
let name = codec
Expand Down Expand Up @@ -772,11 +776,13 @@ pub(crate) struct MediaSection {
pub(crate) data: bool,
pub(crate) rid_map: Vec<SimulcastRid>,
pub(crate) offered_direction: Option<RTCRtpTransceiverDirection>,
pub(crate) extmap_allow_mixed: bool,
}

pub(crate) struct PopulateSdpParams {
pub(crate) media_description_fingerprint: bool,
pub(crate) is_icelite: bool,
pub(crate) extmap_allow_mixed: bool,
pub(crate) connection_role: ConnectionRole,
pub(crate) ice_gathering_state: RTCIceGatheringState,
pub(crate) match_bundle_group: Option<String>,
Expand Down Expand Up @@ -876,6 +882,11 @@ pub(crate) async fn populate_sdp(
d = d.with_value_attribute(ATTR_KEY_GROUP.to_owned(), bundle_value);
}

if params.extmap_allow_mixed {
// RFC 8285 6.
d = d.with_property_attribute(ATTR_KEY_EXTMAP_ALLOW_MIXED.to_owned());
}

Ok(d)
}

Expand Down
9 changes: 9 additions & 0 deletions webrtc/src/peer_connection/sdp/sdp_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,7 @@ async fn fingerprint_test(
let params = PopulateSdpParams {
media_description_fingerprint: sdpmedia_description_fingerprints,
is_icelite: false,
extmap_allow_mixed: false,
connection_role: ConnectionRole::Active,
ice_gathering_state: RTCIceGatheringState::New,
match_bundle_group: None,
Expand Down Expand Up @@ -777,6 +778,7 @@ async fn test_populate_sdp() -> Result<()> {
let params = PopulateSdpParams {
media_description_fingerprint: se.sdp_media_level_fingerprints,
is_icelite: se.candidates.ice_lite,
extmap_allow_mixed: true,
connection_role: DEFAULT_DTLS_ROLE_OFFER.to_connection_role(),
ice_gathering_state: RTCIceGatheringState::Complete,
match_bundle_group: None,
Expand Down Expand Up @@ -882,6 +884,7 @@ async fn test_populate_sdp() -> Result<()> {
let params = PopulateSdpParams {
media_description_fingerprint: se.sdp_media_level_fingerprints,
is_icelite: se.candidates.ice_lite,
extmap_allow_mixed: true,
connection_role: DEFAULT_DTLS_ROLE_OFFER.to_connection_role(),
ice_gathering_state: RTCIceGatheringState::Complete,
match_bundle_group: None,
Expand Down Expand Up @@ -962,6 +965,7 @@ async fn test_populate_sdp() -> Result<()> {
let params = PopulateSdpParams {
media_description_fingerprint: se.sdp_media_level_fingerprints,
is_icelite: se.candidates.ice_lite,
extmap_allow_mixed: true,
connection_role: DEFAULT_DTLS_ROLE_OFFER.to_connection_role(),
ice_gathering_state: RTCIceGatheringState::Complete,
match_bundle_group: None,
Expand All @@ -981,6 +985,8 @@ async fn test_populate_sdp() -> Result<()> {
offer_sdp.attribute(ATTR_KEY_GROUP),
Some(&"BUNDLE video".to_owned())
);

assert!(offer_sdp.has_attribute(ATTR_KEY_EXTMAP_ALLOW_MIXED));
}

//"Bundle matched"
Expand Down Expand Up @@ -1057,6 +1063,7 @@ async fn test_populate_sdp() -> Result<()> {
let params = PopulateSdpParams {
media_description_fingerprint: se.sdp_media_level_fingerprints,
is_icelite: se.candidates.ice_lite,
extmap_allow_mixed: true,
connection_role: DEFAULT_DTLS_ROLE_OFFER.to_connection_role(),
ice_gathering_state: RTCIceGatheringState::Complete,
match_bundle_group: Some("audio".to_owned()),
Expand Down Expand Up @@ -1122,6 +1129,7 @@ async fn test_populate_sdp() -> Result<()> {
let params = PopulateSdpParams {
media_description_fingerprint: se.sdp_media_level_fingerprints,
is_icelite: se.candidates.ice_lite,
extmap_allow_mixed: true,
connection_role: DEFAULT_DTLS_ROLE_OFFER.to_connection_role(),
ice_gathering_state: RTCIceGatheringState::Complete,
match_bundle_group: Some("".to_owned()),
Expand Down Expand Up @@ -1231,6 +1239,7 @@ async fn test_populate_sdp_reject() -> Result<()> {
let params = PopulateSdpParams {
media_description_fingerprint: se.sdp_media_level_fingerprints,
is_icelite: se.candidates.ice_lite,
extmap_allow_mixed: true,
connection_role: DEFAULT_DTLS_ROLE_OFFER.to_connection_role(),
ice_gathering_state: RTCIceGatheringState::Complete,
match_bundle_group: None,
Expand Down

0 comments on commit 23bbc1f

Please sign in to comment.