@@ -787,7 +787,8 @@ extension MSRPApplication {
787787
788788 if let existingTalkerRegistration = await _findTalkerRegistration (
789789 for: streamID,
790- participant: participant
790+ participant: participant,
791+ attributeType: . talkerAdvertise
791792 ) , existingTalkerRegistration. dataFrameParameters != dataFrameParameters {
792793 _logger
793794 . error (
@@ -1110,32 +1111,42 @@ extension MSRPApplication {
11101111
11111112 private func _findTalkerRegistration(
11121113 for streamID: MSRPStreamID ,
1113- participant: Participant < MSRPApplication >
1114+ participant: Participant < MSRPApplication > ,
1115+ attributeType: MSRPAttributeType ?
11141116 ) async -> ( any MSRPTalkerValue ) ? {
1115- if let value = await participant. findAttribute (
1116- attributeType: MSRPAttributeType . talkerAdvertise. rawValue,
1117- matching: . matchAnyIndex( streamID. index)
1118- ) {
1117+ if attributeType == nil || attributeType == . talkerAdvertise,
1118+ let value = await participant. findAttribute (
1119+ attributeType: MSRPAttributeType . talkerAdvertise. rawValue,
1120+ matching: . matchAnyIndex( streamID. index)
1121+ )
1122+ {
11191123 value. 1 as? ( any MSRPTalkerValue )
1120- } else if let value = await participant. findAttribute (
1121- attributeType: MSRPAttributeType . talkerFailed. rawValue,
1122- matching: . matchAnyIndex( streamID. index)
1123- ) {
1124+ } else if attributeType == nil || attributeType == . talkerFailed,
1125+ let value = await participant. findAttribute (
1126+ attributeType: MSRPAttributeType . talkerFailed. rawValue,
1127+ matching: . matchAnyIndex( streamID. index)
1128+ )
1129+ {
11241130 value. 1 as? ( any MSRPTalkerValue )
11251131 } else {
11261132 nil
11271133 }
11281134 }
11291135
11301136 private func _findTalkerRegistration(
1131- for streamID: MSRPStreamID
1137+ for streamID: MSRPStreamID ,
1138+ attributeType: MSRPAttributeType ? = nil
11321139 ) async throws -> TalkerRegistration ? {
11331140 var talkerRegistration : TalkerRegistration ?
11341141
1142+ // note: it's safe to enumerate all participants, because we only expect so
1143+ // see a talker for a given stream ID registered on a single port
1144+ // (otherwise, it is an error)
11351145 await apply { participant in
11361146 guard let participantTalker = await _findTalkerRegistration (
11371147 for: streamID,
1138- participant: participant
1148+ participant: participant,
1149+ attributeType: attributeType
11391150 ) else {
11401151 return
11411152 }
@@ -1550,14 +1561,25 @@ extension MSRPApplication {
15501561 // behavior described in 35.2.4.4.1.
15511562 guard let talkerParticipant = try ? findParticipant ( port: port) else { return }
15521563
1564+ let otherTalkerRegistration =
1565+ await _findTalkerRegistration (
1566+ for: streamID,
1567+ participant: talkerParticipant,
1568+ attributeType: talkerValue. declarationType!. talkerComplement
1569+ )
1570+
15531571 try await apply { participant in
15541572 guard participant. port != port else { return } // don't propagate to source port
15551573
1556- // If this participant has active listeners, propagate a leave back to the talker
1557- if let listenerRegistration = await _findListenerRegistration (
1558- for: streamID,
1559- participant: participant
1560- ) {
1574+ // if a different talker attribute is registered on the talker port,
1575+ // don't propagate the listener leave back to the talker to avoid a race
1576+ // whilst deregistering
1577+ if otherTalkerRegistration == nil ,
1578+ let listenerRegistration = await _findListenerRegistration (
1579+ for: streamID,
1580+ participant: participant
1581+ )
1582+ {
15611583 try await talkerParticipant. leave (
15621584 attributeType: MSRPAttributeType . listener. rawValue,
15631585 attributeSubtype: listenerRegistration. 1 . rawValue,
0 commit comments