Skip to content

Commit 1ad10c3

Browse files
authored
peer_connection: sdp: allow inactive m= to have conflicting credentials (#585)
1 parent edf0a53 commit 1ad10c3

File tree

2 files changed

+86
-30
lines changed

2 files changed

+86
-30
lines changed

webrtc/src/peer_connection/sdp/mod.rs

Lines changed: 41 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -933,22 +933,44 @@ pub(crate) async fn extract_ice_details(
933933
desc: &SessionDescription,
934934
) -> Result<(String, String, Vec<RTCIceCandidate>)> {
935935
let mut candidates = vec![];
936-
let mut remote_pwds = vec![];
937-
let mut remote_ufrags = vec![];
938936

939-
if let Some(ufrag) = desc.attribute("ice-ufrag") {
940-
remote_ufrags.push(ufrag.clone());
941-
}
942-
if let Some(pwd) = desc.attribute("ice-pwd") {
943-
remote_pwds.push(pwd.clone());
944-
}
937+
// Backup ufrag/pwd is the first inactive credentials found.
938+
// We will return the backup credentials to solve the corner case where
939+
// all media lines/transceivers are set to inactive.
940+
//
941+
// This should probably be handled in a better way by the caller.
942+
let mut backup_ufrag = None;
943+
let mut backup_pwd = None;
944+
945+
let mut remote_ufrag = desc.attribute("ice-ufrag").map(|s| s.as_str());
946+
let mut remote_pwd = desc.attribute("ice-pwd").map(|s| s.as_str());
945947

946948
for m in &desc.media_descriptions {
947-
if let Some(ufrag) = m.attribute("ice-ufrag").and_then(|o| o) {
948-
remote_ufrags.push(ufrag.to_owned());
949+
let ufrag = m.attribute("ice-ufrag").and_then(|o| o);
950+
let pwd = m.attribute("ice-pwd").and_then(|o| o);
951+
952+
if m.attribute(ATTR_KEY_INACTIVE).is_some() {
953+
if backup_ufrag.is_none() {
954+
backup_ufrag = ufrag;
955+
}
956+
if backup_pwd.is_none() {
957+
backup_pwd = pwd;
958+
}
959+
continue;
960+
}
961+
962+
if remote_ufrag.is_none() {
963+
remote_ufrag = ufrag;
949964
}
950-
if let Some(pwd) = m.attribute("ice-pwd").and_then(|o| o) {
951-
remote_pwds.push(pwd.to_owned());
965+
if remote_pwd.is_none() {
966+
remote_pwd = pwd;
967+
}
968+
969+
if ufrag.is_some() && ufrag != remote_ufrag {
970+
return Err(Error::ErrSessionDescriptionConflictingIceUfrag);
971+
}
972+
if pwd.is_some() && pwd != remote_pwd {
973+
return Err(Error::ErrSessionDescriptionConflictingIcePwd);
952974
}
953975

954976
for a in &m.attributes {
@@ -962,25 +984,14 @@ pub(crate) async fn extract_ice_details(
962984
}
963985
}
964986

965-
if remote_ufrags.is_empty() {
966-
return Err(Error::ErrSessionDescriptionMissingIceUfrag);
967-
} else if remote_pwds.is_empty() {
968-
return Err(Error::ErrSessionDescriptionMissingIcePwd);
969-
}
970-
971-
for m in 1..remote_ufrags.len() {
972-
if remote_ufrags[m] != remote_ufrags[0] {
973-
return Err(Error::ErrSessionDescriptionConflictingIceUfrag);
974-
}
975-
}
976-
977-
for m in 1..remote_pwds.len() {
978-
if remote_pwds[m] != remote_pwds[0] {
979-
return Err(Error::ErrSessionDescriptionConflictingIcePwd);
980-
}
981-
}
987+
let remote_ufrag = remote_ufrag
988+
.or(backup_ufrag)
989+
.ok_or(Error::ErrSessionDescriptionMissingIceUfrag)?;
990+
let remote_pwd = remote_pwd
991+
.or(backup_pwd)
992+
.ok_or(Error::ErrSessionDescriptionMissingIcePwd)?;
982993

983-
Ok((remote_ufrags[0].clone(), remote_pwds[0].clone(), candidates))
994+
Ok((remote_ufrag.to_owned(), remote_pwd.to_owned(), candidates))
984995
}
985996

986997
pub(crate) fn have_application_media_section(desc: &SessionDescription) -> bool {

webrtc/src/peer_connection/sdp/sdp_test.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,51 @@ async fn test_extract_ice_details() -> Result<()> {
254254
);
255255
}
256256

257+
//"Allow Conflict ufrag from inactive MediaDescription"
258+
{
259+
let s = SessionDescription {
260+
media_descriptions: vec![
261+
MediaDescription {
262+
attributes: vec![
263+
Attribute {
264+
key: "ice-ufrag".to_owned(),
265+
value: Some(DEFAULT_UFRAG.to_owned()),
266+
},
267+
Attribute {
268+
key: "ice-pwd".to_owned(),
269+
value: Some(DEFAULT_PWD.to_owned()),
270+
},
271+
],
272+
..Default::default()
273+
},
274+
MediaDescription {
275+
attributes: vec![
276+
Attribute {
277+
key: "ice-ufrag".to_owned(),
278+
value: Some("invalidUfrag".to_owned()),
279+
},
280+
Attribute {
281+
key: "ice-pwd".to_owned(),
282+
value: Some(DEFAULT_PWD.to_owned()),
283+
},
284+
Attribute {
285+
key: ATTR_KEY_INACTIVE.to_owned(),
286+
value: None,
287+
},
288+
],
289+
..Default::default()
290+
},
291+
],
292+
..Default::default()
293+
};
294+
295+
let (ufrag, pwd, _) = extract_ice_details(&s)
296+
.await
297+
.expect("should allow conflicting ICE ufrag when MediaDescription is inactive");
298+
assert_eq!(ufrag, DEFAULT_UFRAG);
299+
assert_eq!(pwd, DEFAULT_PWD);
300+
}
301+
257302
Ok(())
258303
}
259304

0 commit comments

Comments
 (0)