From 8fbe9dc225a3fe723068781fa687f7dc2704f38a Mon Sep 17 00:00:00 2001
From: Boris Zbarsky <bzbarsky@apple.com>
Date: Tue, 4 Mar 2025 12:20:56 -0500
Subject: [PATCH] Don't interrupt a CASE attempt triggered by
 _deviceMayBeReachable.

There's a really good chance this attempt will in fact succeed, so don't touch
it.

As a followup, we will need to figure out a better state machine here.
---
 src/darwin/Framework/CHIP/MTRDevice_Concrete.mm | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/src/darwin/Framework/CHIP/MTRDevice_Concrete.mm b/src/darwin/Framework/CHIP/MTRDevice_Concrete.mm
index 1aa037e9769efe..3e74e5f3019958 100644
--- a/src/darwin/Framework/CHIP/MTRDevice_Concrete.mm
+++ b/src/darwin/Framework/CHIP/MTRDevice_Concrete.mm
@@ -58,6 +58,8 @@
 
 static NSString * const sLastInitialSubscribeLatencyKey = @"lastInitialSubscribeLatency";
 
+static NSString * const sDeviceMayBeReachableReason = @"SPI client indicated the device may now be reachable";
+
 // Not static, because these are public API.
 NSString * const MTRPreviousDataKey = @"previousData";
 NSString * const MTRDataVersionKey = @"dataVersion";
@@ -306,6 +308,7 @@ @interface MTRDevice_Concrete ()
 //   Actively receiving priming report
 
 @property (nonatomic) MTRInternalDeviceState internalDeviceState;
+@property (nonatomic) BOOL doingCASEAttemptForDeviceMayBeReachable;
 
 #define MTRDEVICE_SUBSCRIPTION_ATTEMPT_MIN_WAIT_SECONDS (1)
 #define MTRDEVICE_SUBSCRIPTION_ATTEMPT_MAX_WAIT_SECONDS (3600)
@@ -470,6 +473,7 @@ - (instancetype)initWithNodeID:(NSNumber *)nodeID controller:(MTRDeviceControlle
         _state = MTRDeviceStateUnknown;
         _internalDeviceState = MTRInternalDeviceStateUnsubscribed;
         _internalDeviceStateForDescription = MTRInternalDeviceStateUnsubscribed;
+        _doingCASEAttemptForDeviceMayBeReachable = NO;
         if (controller.controllerDataStore) {
             _persistedClusterData = [[NSCache alloc] init];
         } else {
@@ -1049,7 +1053,7 @@ - (void)_triggerResubscribeWithReason:(NSString *)reason nodeLikelyReachable:(BO
             subscriptionCallback->ResetResubscriptionBackoff();
         }
         readClientToResubscribe->TriggerResubscribeIfScheduled(reason.UTF8String);
-    } else if (((_internalDeviceState == MTRInternalDeviceStateSubscribing) || shouldReattemptSubscription) && nodeLikelyReachable) {
+    } else if (((_internalDeviceState == MTRInternalDeviceStateSubscribing && !self.doingCASEAttemptForDeviceMayBeReachable) || shouldReattemptSubscription) && 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.
 
@@ -2745,6 +2749,9 @@ - (void)_setupSubscriptionWithReason:(NSString *)reason
     [self _changeInternalState:MTRInternalDeviceStateSubscribing];
 
     MTR_LOG("%@ setting up subscription with reason: %@", self, reason);
+    if ([reason hasPrefix:sDeviceMayBeReachableReason]) {
+        self.doingCASEAttemptForDeviceMayBeReachable = YES;
+    }
 
     __block bool markUnreachableAfterWait = true;
 #ifdef DEBUG
@@ -2784,6 +2791,8 @@ - (void)_setupSubscriptionWithReason:(NSString *)reason
                            mtr_strongify(self);
                            VerifyOrReturn(self, MTR_LOG_DEBUG("_setupSubscriptionWithReason directlyGetSessionForNode called back with nil MTRDevice"));
 
+                           self.doingCASEAttemptForDeviceMayBeReachable = NO;
+
                            if (error != nil) {
                                MTR_LOG_ERROR("%@ getSessionForNode error %@", self, error);
                                [self->_deviceController asyncDispatchToMatterQueue:^{
@@ -4844,7 +4853,7 @@ - (void)_deviceMayBeReachable
         std::lock_guard lock(self->_lock);
         // Use _ensureSubscriptionForExistingDelegates so that the subscriptions
         // will go through the pool as needed, not necessarily happen immediately.
-        [self _ensureSubscriptionForExistingDelegates:@"SPI client indicated the device may now be reachable"];
+        [self _ensureSubscriptionForExistingDelegates:sDeviceMayBeReachableReason];
     } errorHandler:nil];
 }