Skip to content

Commit f0241d7

Browse files
committed
MSRP: propagate leave to talker only if complementary attribute unregistered
When propagating listener leave back to talker port after talker deregistration, check if the complementary talker attribute type is still registered (e.g., if talkerAdvertise exists when processing talkerFailed leave). Only propagate if no other talker attribute is registered, avoiding race conditions during talker attribute type transitions.
1 parent 282eb78 commit f0241d7

File tree

1 file changed

+39
-17
lines changed

1 file changed

+39
-17
lines changed

Sources/MRP/Applications/MSRP/MSRPApplication.swift

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)