@@ -719,96 +719,156 @@ func getPeerDirection(media *sdp.MediaDescription) RTPTransceiverDirection {
719
719
return RTPTransceiverDirectionUnknown
720
720
}
721
721
722
- func extractFingerprint (desc * sdp.SessionDescription ) ( string , string , error ) {
723
- fingerprints := [] string {}
722
+ func extractBundleID (desc * sdp.SessionDescription ) string {
723
+ groupAttribute , _ := desc . Attribute ( sdp . AttrKeyGroup )
724
724
725
- if fingerprint , haveFingerprint := desc .Attribute ("fingerprint" ); haveFingerprint {
726
- fingerprints = append (fingerprints , fingerprint )
725
+ isBundled := strings .Contains (groupAttribute , "BUNDLE" )
726
+
727
+ if ! isBundled {
728
+ return ""
727
729
}
728
730
729
- for _ , m := range desc . MediaDescriptions {
730
- if fingerprint , haveFingerprint := m . Attribute ( "fingerprint" ); haveFingerprint {
731
- fingerprints = append ( fingerprints , fingerprint )
732
- }
731
+ bundleIDs := strings . Split ( groupAttribute , " " )
732
+
733
+ if len ( bundleIDs ) < 2 {
734
+ return ""
733
735
}
734
736
735
- if len (fingerprints ) < 1 {
736
- return "" , "" , ErrSessionDescriptionNoFingerprint
737
+ return bundleIDs [1 ]
738
+ }
739
+
740
+ func extractFingerprint (desc * sdp.SessionDescription ) (string , string , error ) { //nolint: gocognit
741
+ fingerprint := ""
742
+
743
+ // Fingerprint on session level has highest priority
744
+ if sessionFingerprint , haveFingerprint := desc .Attribute ("fingerprint" ); haveFingerprint {
745
+ fingerprint = sessionFingerprint
737
746
}
738
747
739
- for _ , m := range fingerprints {
740
- if m != fingerprints [0 ] {
741
- return "" , "" , ErrSessionDescriptionConflictingFingerprints
748
+ if fingerprint == "" {
749
+ bundleID := extractBundleID (desc )
750
+ if bundleID != "" {
751
+ // Locate the fingerprint of the bundled media section
752
+ for _ , m := range desc .MediaDescriptions {
753
+ if mid , haveMid := m .Attribute ("mid" ); haveMid {
754
+ if mid == bundleID && fingerprint == "" {
755
+ if mediaFingerprint , haveFingerprint := m .Attribute ("fingerprint" ); haveFingerprint {
756
+ fingerprint = mediaFingerprint
757
+ }
758
+ }
759
+ }
760
+ }
761
+ } else {
762
+ // Take the fingerprint from the first media section which has one.
763
+ // Note: According to Bundle spec each media section would have it's own transport
764
+ // with it's own cert and fingerprint each, so we would need to return a list.
765
+ for _ , m := range desc .MediaDescriptions {
766
+ mediaFingerprint , haveFingerprint := m .Attribute ("fingerprint" )
767
+ if haveFingerprint && fingerprint == "" {
768
+ fingerprint = mediaFingerprint
769
+ }
770
+ }
742
771
}
743
772
}
744
773
745
- parts := strings .Split (fingerprints [0 ], " " )
774
+ if fingerprint == "" {
775
+ return "" , "" , ErrSessionDescriptionNoFingerprint
776
+ }
777
+
778
+ parts := strings .Split (fingerprint , " " )
746
779
if len (parts ) != 2 {
747
780
return "" , "" , ErrSessionDescriptionInvalidFingerprint
748
781
}
749
782
return parts [1 ], parts [0 ], nil
750
783
}
751
784
752
- func extractICEDetails (desc * sdp.SessionDescription , log logging.LeveledLogger ) (string , string , []ICECandidate , error ) { // nolint:gocognit
785
+ func extractICEDetailsFromMedia (media * sdp.MediaDescription , log logging.LeveledLogger ) (string , string , []ICECandidate , error ) {
786
+ remoteUfrag := ""
787
+ remotePwd := ""
753
788
candidates := []ICECandidate {}
754
- remotePwds := []string {}
755
- remoteUfrags := []string {}
756
789
790
+ if ufrag , haveUfrag := media .Attribute ("ice-ufrag" ); haveUfrag {
791
+ remoteUfrag = ufrag
792
+ }
793
+ if pwd , havePwd := media .Attribute ("ice-pwd" ); havePwd {
794
+ remotePwd = pwd
795
+ }
796
+ for _ , a := range media .Attributes {
797
+ if a .IsICECandidate () {
798
+ c , err := ice .UnmarshalCandidate (a .Value )
799
+ if err != nil {
800
+ if errors .Is (err , ice .ErrUnknownCandidateTyp ) || errors .Is (err , ice .ErrDetermineNetworkType ) {
801
+ log .Warnf ("Discarding remote candidate: %s" , err )
802
+ continue
803
+ }
804
+ return "" , "" , nil , err
805
+ }
806
+
807
+ candidate , err := newICECandidateFromICE (c )
808
+ if err != nil {
809
+ return "" , "" , nil , err
810
+ }
811
+
812
+ candidates = append (candidates , candidate )
813
+ }
814
+ }
815
+
816
+ return remoteUfrag , remotePwd , candidates , nil
817
+ }
818
+
819
+ func extractICEDetails (desc * sdp.SessionDescription , log logging.LeveledLogger ) (string , string , []ICECandidate , error ) { // nolint:gocognit
820
+ remoteCandidates := []ICECandidate {}
821
+ remotePwd := ""
822
+ remoteUfrag := ""
823
+
824
+ // Ufrag and Pw are allow at session level and thus have highest prio
757
825
if ufrag , haveUfrag := desc .Attribute ("ice-ufrag" ); haveUfrag {
758
- remoteUfrags = append ( remoteUfrags , ufrag )
826
+ remoteUfrag = ufrag
759
827
}
760
828
if pwd , havePwd := desc .Attribute ("ice-pwd" ); havePwd {
761
- remotePwds = append ( remotePwds , pwd )
829
+ remotePwd = pwd
762
830
}
763
831
764
- for _ , m := range desc .MediaDescriptions {
765
- if ufrag , haveUfrag := m .Attribute ("ice-ufrag" ); haveUfrag {
766
- remoteUfrags = append (remoteUfrags , ufrag )
767
- }
768
- if pwd , havePwd := m .Attribute ("ice-pwd" ); havePwd {
769
- remotePwds = append (remotePwds , pwd )
770
- }
832
+ bundleID := extractBundleID (desc )
833
+ missing := true
771
834
772
- for _ , a := range m .Attributes {
773
- if a .IsICECandidate () {
774
- c , err := ice .UnmarshalCandidate (a .Value )
835
+ for _ , m := range desc .MediaDescriptions {
836
+ mid := getMidValue (m )
837
+ // If bundled, only take ICE detail from bundle master section
838
+ if bundleID != "" {
839
+ if mid == bundleID {
840
+ ufrag , pwd , candidates , err := extractICEDetailsFromMedia (m , log )
775
841
if err != nil {
776
- if errors .Is (err , ice .ErrUnknownCandidateTyp ) || errors .Is (err , ice .ErrDetermineNetworkType ) {
777
- log .Warnf ("Discarding remote candidate: %s" , err )
778
- continue
779
- }
780
842
return "" , "" , nil , err
781
843
}
782
-
783
- candidate , err := newICECandidateFromICE (c )
784
- if err != nil {
785
- return "" , "" , nil , err
844
+ if remoteUfrag == "" && ufrag != "" {
845
+ remoteUfrag = ufrag
846
+ remotePwd = pwd
786
847
}
787
-
788
- candidates = append (candidates , candidate )
848
+ remoteCandidates = candidates
849
+ }
850
+ } else if missing {
851
+ // For not-bundled, take ICE details from the first media section
852
+ ufrag , pwd , candidates , err := extractICEDetailsFromMedia (m , log )
853
+ if err != nil {
854
+ return "" , "" , nil , err
855
+ }
856
+ if remoteUfrag == "" && ufrag != "" {
857
+ remoteUfrag = ufrag
858
+ remotePwd = pwd
789
859
}
860
+ remoteCandidates = candidates
861
+ missing = false
790
862
}
791
863
}
792
864
793
- if len ( remoteUfrags ) == 0 {
865
+ if remoteUfrag == "" {
794
866
return "" , "" , nil , ErrSessionDescriptionMissingIceUfrag
795
- } else if len ( remotePwds ) == 0 {
867
+ } else if remotePwd == "" {
796
868
return "" , "" , nil , ErrSessionDescriptionMissingIcePwd
797
869
}
798
870
799
- for _ , m := range remoteUfrags {
800
- if m != remoteUfrags [0 ] {
801
- return "" , "" , nil , ErrSessionDescriptionConflictingIceUfrag
802
- }
803
- }
804
-
805
- for _ , m := range remotePwds {
806
- if m != remotePwds [0 ] {
807
- return "" , "" , nil , ErrSessionDescriptionConflictingIcePwd
808
- }
809
- }
810
-
811
- return remoteUfrags [0 ], remotePwds [0 ], candidates , nil
871
+ return remoteUfrag , remotePwd , remoteCandidates , nil
812
872
}
813
873
814
874
func haveApplicationMediaSection (desc * sdp.SessionDescription ) bool {
0 commit comments