@@ -933,22 +933,44 @@ pub(crate) async fn extract_ice_details(
933
933
desc : & SessionDescription ,
934
934
) -> Result < ( String , String , Vec < RTCIceCandidate > ) > {
935
935
let mut candidates = vec ! [ ] ;
936
- let mut remote_pwds = vec ! [ ] ;
937
- let mut remote_ufrags = vec ! [ ] ;
938
936
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 ( ) ) ;
945
947
946
948
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;
949
964
}
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 ) ;
952
974
}
953
975
954
976
for a in & m. attributes {
@@ -962,25 +984,14 @@ pub(crate) async fn extract_ice_details(
962
984
}
963
985
}
964
986
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 ) ?;
982
993
983
- Ok ( ( remote_ufrags [ 0 ] . clone ( ) , remote_pwds [ 0 ] . clone ( ) , candidates) )
994
+ Ok ( ( remote_ufrag . to_owned ( ) , remote_pwd . to_owned ( ) , candidates) )
984
995
}
985
996
986
997
pub ( crate ) fn have_application_media_section ( desc : & SessionDescription ) -> bool {
0 commit comments