[Matter.framework] Invalidate the CASE session if something calls TriggerResubscriptionWithReason and it has not been established yet (#36298)
diff --git a/src/app/CASESessionManager.cpp b/src/app/CASESessionManager.cpp
index 766e601..4222421 100644
--- a/src/app/CASESessionManager.cpp
+++ b/src/app/CASESessionManager.cpp
@@ -188,6 +188,12 @@
peerId, MakeOptional(Transport::SecureSession::Type::kCASE), transportPayloadCapability);
}
+void CASESessionManager::ReleaseSession(const ScopedNodeId & peerId)
+{
+ auto * session = mConfig.sessionSetupPool->FindSessionSetup(peerId, false);
+ ReleaseSession(session);
+}
+
void CASESessionManager::ReleaseSession(OperationalSessionSetup * session)
{
if (session != nullptr)
diff --git a/src/app/CASESessionManager.h b/src/app/CASESessionManager.h
index e536a62..c6d0a8c 100644
--- a/src/app/CASESessionManager.h
+++ b/src/app/CASESessionManager.h
@@ -142,6 +142,7 @@
#endif // CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
TransportPayloadCapability transportPayloadCapability = TransportPayloadCapability::kMRPPayload);
+ void ReleaseSession(const ScopedNodeId & peerId);
void ReleaseSessionsForFabric(FabricIndex fabricIndex);
void ReleaseAllSessions();
diff --git a/src/controller/CHIPDeviceController.h b/src/controller/CHIPDeviceController.h
index 2ec0203..0536856 100644
--- a/src/controller/CHIPDeviceController.h
+++ b/src/controller/CHIPDeviceController.h
@@ -204,6 +204,16 @@
return nullptr;
}
+ CASESessionManager * CASESessionMgr()
+ {
+ if (mSystemState)
+ {
+ return mSystemState->CASESessionMgr();
+ }
+
+ return nullptr;
+ }
+
Messaging::ExchangeManager * ExchangeMgr()
{
if (mSystemState != nullptr)
diff --git a/src/darwin/Framework/CHIP/MTRDeviceController_Concrete.h b/src/darwin/Framework/CHIP/MTRDeviceController_Concrete.h
index 0cfb25f..f9f1e9d 100644
--- a/src/darwin/Framework/CHIP/MTRDeviceController_Concrete.h
+++ b/src/darwin/Framework/CHIP/MTRDeviceController_Concrete.h
@@ -179,6 +179,12 @@
- (void)invalidateCASESessionForNode:(NSNumber *)nodeID;
/**
+ * Invalidate the CASE session establishment for the specified node ID.
+ * Must not be called on the Matter event queue.
+ */
+- (void)invalidateCASESessionEstablishmentForNode:(NSNumber *)nodeID;
+
+/**
* Download log of the desired type from the device.
*/
- (void)downloadLogFromNodeWithID:(NSNumber *)nodeID
diff --git a/src/darwin/Framework/CHIP/MTRDeviceController_Concrete.mm b/src/darwin/Framework/CHIP/MTRDeviceController_Concrete.mm
index 1a164e5..74e3437 100644
--- a/src/darwin/Framework/CHIP/MTRDeviceController_Concrete.mm
+++ b/src/darwin/Framework/CHIP/MTRDeviceController_Concrete.mm
@@ -1619,6 +1619,17 @@
[self syncRunOnWorkQueue:block error:nil];
}
+- (void)invalidateCASESessionEstablishmentForNode:(NSNumber *)nodeID;
+{
+ auto block = ^{
+ auto caseSessionMgr = self->_cppCommissioner->CASESessionMgr();
+ VerifyOrDie(caseSessionMgr != nullptr);
+ caseSessionMgr->ReleaseSession(self->_cppCommissioner->GetPeerScopedId(nodeID.unsignedLongLongValue));
+ };
+
+ [self syncRunOnWorkQueue:block error:nil];
+}
+
- (void)operationalInstanceAdded:(NSNumber *)nodeID
{
// Don't use deviceForNodeID here, because we don't want to create the
diff --git a/src/darwin/Framework/CHIP/MTRDevice_Concrete.mm b/src/darwin/Framework/CHIP/MTRDevice_Concrete.mm
index a7b5d25..5668f61 100644
--- a/src/darwin/Framework/CHIP/MTRDevice_Concrete.mm
+++ b/src/darwin/Framework/CHIP/MTRDevice_Concrete.mm
@@ -898,6 +898,12 @@
subscriptionCallback->ResetResubscriptionBackoff();
}
readClientToResubscribe->TriggerResubscribeIfScheduled(reason.UTF8String);
+ } else if (_internalDeviceState == MTRInternalDeviceStateSubscribing && nodeLikelyReachable) {
+ // If we have reason to suspect that the node is now reachable and we haven’t established a
+ // CASE session yet, let’s consider it to be stalled and invalidate the pairing session.
+ dispatch_async(self.queue, ^{
+ [[self _concreteController] invalidateCASESessionEstablishmentForNode:self->_nodeID];
+ });
}
}