Skip to content

Commit

Permalink
Make MTRDevice mark itself as unreachable after 10s of waiting for a …
Browse files Browse the repository at this point in the history
…subscription (project-chip#32579)

* First commit

* Restyled by whitespace

* Restyled by clang-format

---------

Co-authored-by: Restyled.io <[email protected]>
  • Loading branch information
woody-apple and restyled-commits authored Mar 14, 2024
1 parent 84970a0 commit 0aa09e0
Showing 1 changed file with 33 additions and 12 deletions.
45 changes: 33 additions & 12 deletions src/darwin/Framework/CHIP/MTRDevice.mm
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@
NSString * const MTRPreviousDataKey = @"previousData";
NSString * const MTRDataVersionKey = @"dataVersion";

#define kTimeToWaitBeforeMarkingUnreachableAfterSettingUpSubscription 10

// Consider moving utility classes to their own file
#pragma mark - Utility Classes
// This class is for storing weak references in a container
Expand Down Expand Up @@ -125,6 +127,12 @@ - (id)strongObject
} // anonymous namespace

#pragma mark - MTRDevice
typedef NS_ENUM(NSUInteger, MTRInternalDeviceState) {
MTRInternalDeviceStateUnsubscribed = 0,
MTRInternalDeviceStateSubscribing = 1,
MTRInternalDeviceStateSubscribed = 2
};

typedef NS_ENUM(NSUInteger, MTRDeviceExpectedValueFieldIndex) {
MTRDeviceExpectedValueFieldExpirationTimeIndex = 0,
MTRDeviceExpectedValueFieldValueIndex = 1,
Expand Down Expand Up @@ -157,18 +165,10 @@ @interface MTRDevice ()
@property (nonatomic) BOOL receivingPrimingReport;

// TODO: instead of all the BOOL properties that are some facet of the state, move to internal state machine that has (at least):
// Unsubscribed (not attemping)
// Attempting subscription
// Subscribed (gotten subscription response / in steady state with no OnError/OnDone)
// Actively receiving report
// Actively receiving priming report

/**
* If subscriptionActive is true that means that either we are in the middle of
* trying to get a CASE session for the publisher or we have a live ReadClient
* right now (possibly with a lost subscription and trying to re-subscribe).
*/
@property (nonatomic) BOOL subscriptionActive;
@property (nonatomic) MTRInternalDeviceState internalDeviceState;

#define MTRDEVICE_SUBSCRIPTION_ATTEMPT_MIN_WAIT_SECONDS (1)
#define MTRDEVICE_SUBSCRIPTION_ATTEMPT_MAX_WAIT_SECONDS (3600)
Expand Down Expand Up @@ -640,6 +640,7 @@ - (void)_handleSubscriptionEstablished

// reset subscription attempt wait time when subscription succeeds
_lastSubscriptionAttemptWait = 0;
_internalDeviceState = MTRInternalDeviceStateSubscribed;

// As subscription is established, check if the delegate needs to be informed
if (!_delegateDeviceCachePrimedCalled) {
Expand All @@ -663,7 +664,7 @@ - (void)_handleSubscriptionError:(NSError *)error
{
os_unfair_lock_lock(&self->_lock);

_subscriptionActive = NO;
_internalDeviceState = MTRInternalDeviceStateUnsubscribed;
_unreportedEvents = nil;

[self _changeState:MTRDeviceStateUnreachable];
Expand Down Expand Up @@ -757,6 +758,17 @@ - (void)_handleUnsolicitedMessageFromPublisher
os_unfair_lock_unlock(&self->_lock);
}

- (void)_markDeviceAsUnreachableIfNotSusbcribed
{
os_unfair_lock_assert_owner(&self->_lock);

if (_internalDeviceState >= MTRInternalDeviceStateSubscribed)
return;

MTR_LOG_DEFAULT("%@ still not subscribed, marking the device as unreachable", self);
[self _changeState:MTRDeviceStateUnreachable];
}

- (void)_handleReportBegin
{
os_unfair_lock_lock(&self->_lock);
Expand Down Expand Up @@ -991,11 +1003,20 @@ - (void)_setupSubscription
#endif

// for now just subscribe once
if (_subscriptionActive) {
if (_internalDeviceState > MTRInternalDeviceStateUnsubscribed) {
return;
}

_subscriptionActive = YES;
_internalDeviceState = MTRInternalDeviceStateSubscribing;

// Set up a timer to mark as not reachable if it takes too long to set up a subscription
MTRWeakReference<MTRDevice *> * weakSelf = [MTRWeakReference weakReferenceWithObject:self];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t) (kTimeToWaitBeforeMarkingUnreachableAfterSettingUpSubscription * NSEC_PER_SEC)), self.queue, ^{
MTRDevice * strongSelf = weakSelf.strongObject;
os_unfair_lock_lock(&strongSelf->_lock);
[strongSelf _markDeviceAsUnreachableIfNotSusbcribed];
os_unfair_lock_unlock(&strongSelf->_lock);
});

[_deviceController
getSessionForNode:_nodeID.unsignedLongLongValue
Expand Down

0 comments on commit 0aa09e0

Please sign in to comment.